<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0,viewport-fit=cover"><title>JavaScript 基础 | 学习笔记</title><meta name="author" content="lzoxun"><meta name="copyright" content="lzoxun"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="JS 基础（ECMSscript）概念认识 JavaScript  JS 的作用是给浏览器指令，负责和浏览器进行沟通 JS 是一门编程语言，与计算机交流的计算机语言 JS 和 C、java、Python 等一样是高级语言 JS 基于浏览器，一些内置方法源码需要找JS引擎 ECMA     编程语言的历史 阶段一:机器语言，由二进制 0101010 组成 阶段二:汇编语言，用符号来代替，010101">
<meta property="og:type" content="article">
<meta property="og:title" content="JavaScript 基础">
<meta property="og:url" content="http://example.com/2023/07/22/web/web-script-js/index.html">
<meta property="og:site_name" content="学习笔记">
<meta property="og:description" content="JS 基础（ECMSscript）概念认识 JavaScript  JS 的作用是给浏览器指令，负责和浏览器进行沟通 JS 是一门编程语言，与计算机交流的计算机语言 JS 和 C、java、Python 等一样是高级语言 JS 基于浏览器，一些内置方法源码需要找JS引擎 ECMA     编程语言的历史 阶段一:机器语言，由二进制 0101010 组成 阶段二:汇编语言，用符号来代替，010101">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png">
<meta property="article:published_time" content="2023-07-22T07:14:09.698Z">
<meta property="article:modified_time" content="2023-07-22T07:14:09.698Z">
<meta property="article:author" content="lzoxun">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png"><link rel="shortcut icon" href="/img/favicon.png"><link rel="canonical" href="http://example.com/2023/07/22/web/web-script-js/index.html"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/css/all.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/node-snackbar/dist/snackbar.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox/fancybox.min.css" media="print" onload="this.media='all'"><script>const GLOBAL_CONFIG = {
  root: '/',
  algolia: undefined,
  localSearch: {"path":"/search.xml","preload":true,"top_n_per_article":1,"unescape":true,"languages":{"hits_empty":"找不到您查询的内容：${query}","hits_stats":"共找到 ${hits} 篇文章"}},
  translate: {"defaultEncoding":2,"translateDelay":0,"msgToTraditionalChinese":"繁","msgToSimplifiedChinese":"簡"},
  noticeOutdate: undefined,
  highlight: {"plugin":"highlighjs","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":false},
  copy: {
    success: '复制成功',
    error: '复制错误',
    noSupport: '浏览器不支持'
  },
  relativeDate: {
    homepage: false,
    post: false
  },
  runtime: '',
  dateSuffix: {
    just: '刚刚',
    min: '分钟前',
    hour: '小时前',
    day: '天前',
    month: '个月前'
  },
  copyright: undefined,
  lightbox: 'fancybox',
  Snackbar: {"chs_to_cht":"你已切换为繁体","cht_to_chs":"你已切换为简体","day_to_night":"你已切换为深色模式","night_to_day":"你已切换为浅色模式","bgLight":"#49b1f5","bgDark":"#1f1f1f","position":"bottom-left"},
  source: {
    justifiedGallery: {
      js: 'https://cdn.jsdelivr.net/npm/flickr-justified-gallery/dist/fjGallery.min.js',
      css: 'https://cdn.jsdelivr.net/npm/flickr-justified-gallery/dist/fjGallery.min.css'
    }
  },
  isPhotoFigcaption: false,
  islazyload: true,
  isAnchor: false,
  percent: {
    toc: true,
    rightside: false,
  },
  autoDarkmode: false
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
  title: 'JavaScript 基础',
  isPost: true,
  isHome: false,
  isHighlightShrink: false,
  isToc: true,
  postUpdate: '2023-07-22 15:14:09'
}</script><noscript><style type="text/css">
  #nav {
    opacity: 1
  }
  .justified-gallery img {
    opacity: 1
  }

  #recent-posts time,
  #post-meta time {
    display: inline !important
  }
</style></noscript><script>(win=>{
    win.saveToLocal = {
      set: function setWithExpiry(key, value, ttl) {
        if (ttl === 0) return
        const now = new Date()
        const expiryDay = ttl * 86400000
        const item = {
          value: value,
          expiry: now.getTime() + expiryDay,
        }
        localStorage.setItem(key, JSON.stringify(item))
      },

      get: function getWithExpiry(key) {
        const itemStr = localStorage.getItem(key)

        if (!itemStr) {
          return undefined
        }
        const item = JSON.parse(itemStr)
        const now = new Date()

        if (now.getTime() > item.expiry) {
          localStorage.removeItem(key)
          return undefined
        }
        return item.value
      }
    }
  
    win.getScript = url => new Promise((resolve, reject) => {
      const script = document.createElement('script')
      script.src = url
      script.async = true
      script.onerror = reject
      script.onload = script.onreadystatechange = function() {
        const loadState = this.readyState
        if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
        script.onload = script.onreadystatechange = null
        resolve()
      }
      document.head.appendChild(script)
    })
  
    win.getCSS = (url,id = false) => new Promise((resolve, reject) => {
      const link = document.createElement('link')
      link.rel = 'stylesheet'
      link.href = url
      if (id) link.id = id
      link.onerror = reject
      link.onload = link.onreadystatechange = function() {
        const loadState = this.readyState
        if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
        link.onload = link.onreadystatechange = null
        resolve()
      }
      document.head.appendChild(link)
    })
  
      win.activateDarkMode = function () {
        document.documentElement.setAttribute('data-theme', 'dark')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
        }
      }
      win.activateLightMode = function () {
        document.documentElement.setAttribute('data-theme', 'light')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
        }
      }
      const t = saveToLocal.get('theme')
    
          const now = new Date()
          const hour = now.getHours()
          const isNight = hour <= 6 || hour >= 18
          if (t === undefined) isNight ? activateDarkMode() : activateLightMode()
          else if (t === 'light') activateLightMode()
          else activateDarkMode()
        
      const asideStatus = saveToLocal.get('aside-status')
      if (asideStatus !== undefined) {
        if (asideStatus === 'hide') {
          document.documentElement.classList.add('hide-aside')
        } else {
          document.documentElement.classList.remove('hide-aside')
        }
      }
    
    const detectApple = () => {
      if(/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){
        document.documentElement.classList.add('apple')
      }
    }
    detectApple()
    })(window)</script><meta name="generator" content="Hexo 6.3.0"></head><body><div id="loading-box"><div class="loading-left-bg"></div><div class="loading-right-bg"></div><div class="spinner-box"><div class="configure-border-1"><div class="configure-core"></div></div><div class="configure-border-2"><div class="configure-core"></div></div><div class="loading-word">加载中...</div></div></div><script>(()=>{
  const $loadingBox = document.getElementById('loading-box')
  const $body = document.body
  const preloader = {
    endLoading: () => {
      $body.style.overflow = ''
      $loadingBox.classList.add('loaded')
    },
    initLoading: () => {
      $body.style.overflow = 'hidden'
      $loadingBox.classList.remove('loaded')
    }
  }

  preloader.initLoading()
  window.addEventListener('load',() => { preloader.endLoading() })

  if (false) {
    document.addEventListener('pjax:send', () => { preloader.initLoading() })
    document.addEventListener('pjax:complete', () => { preloader.endLoading() })
  }
})()</script><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src= "" data-lazy-src="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="sidebar-site-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">108</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">1</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">0</div></a></div><hr class="custom-hr"/><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 归档</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div></div></div></div><div class="post" id="body-wrap"><header class="post-bg" id="page-header"><nav id="nav"><span id="blog-info"><a href="/" title="学习笔记"><span class="site-name">学习笔记</span></a></span><div id="menus"><div id="search-button"><a class="site-page social-icon search" href="javascript:void(0);"><i class="fas fa-search fa-fw"></i><span> 搜索</span></a></div><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 归档</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div></div><div id="toggle-menu"><a class="site-page" href="javascript:void(0);"><i class="fas fa-bars fa-fw"></i></a></div></div></nav><div id="post-info"><h1 class="post-title">JavaScript 基础</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2023-07-22T07:14:09.698Z" title="发表于 2023-07-22 15:14:09">2023-07-22</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2023-07-22T07:14:09.698Z" title="更新于 2023-07-22 15:14:09">2023-07-22</time></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-pv-cv" id="" data-flag-title="JavaScript 基础"><i class="far fa-eye fa-fw post-meta-icon"></i><span class="post-meta-label">阅读量:</span><span id="busuanzi_value_page_pv"><i class="fa-solid fa-spinner fa-spin"></i></span></span></div></div></div></header><main class="layout" id="content-inner"><div id="post"><article class="post-content" id="article-container"><h2 id="JS-基础（ECMSscript）"><a href="#JS-基础（ECMSscript）" class="headerlink" title="JS 基础（ECMSscript）"></a>JS 基础（ECMSscript）</h2><h3 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h3><h4 id="认识-JavaScript"><a href="#认识-JavaScript" class="headerlink" title="认识 JavaScript"></a>认识 JavaScript</h4><blockquote>
<ul>
<li>JS 的作用是给浏览器<em>指令</em>，负责和浏览器进行<em>沟通</em></li>
<li>JS 是一门编程语言，与计算机交流的计算机语言</li>
<li>JS 和 C、java、Python 等一样是高级语言</li>
<li>JS 基于浏览器，一些内置方法源码需要找JS引擎<ul>
<li><a target="_blank" rel="noopener" href="https://262.ecma-international.org/">ECMA</a></li>
</ul>
</li>
</ul>
</blockquote>
<h4 id="编程语言的历史"><a href="#编程语言的历史" class="headerlink" title="编程语言的历史"></a>编程语言的历史</h4><ul>
<li>阶段一:<code>机器语言</code>，由二进制 0101010 组成</li>
<li>阶段二:<code>汇编语言</code>，用符号来代替，010101 难以记忆的代码</li>
<li>阶段三:<code>高级语言</code>，接近自然语言，符合我们的思维方式,<em>JavaScript</em>算是一个</li>
</ul>
<h4 id="JavaScript-的历史"><a href="#JavaScript-的历史" class="headerlink" title="JavaScript 的历史"></a>JavaScript 的历史</h4><ul>
<li>1995 浏览器两大厂商<code>网景公司</code>与<code>微软</code></li>
<li>网景<ul>
<li>网景招募<code>Brendan Eich</code>,为了<code>前端表达验证</code>，10 写出了最开始的<code>LiveScript</code>(js)</li>
<li>java 出来后很火爆，就把<code>LiveScript</code>改名<code>JavaScript</code></li>
</ul>
</li>
<li>微软<ul>
<li>微软开始用的是<code>JScript</code></li>
<li>所以为了适配需要两份代码</li>
</ul>
</li>
<li>时间轴<ul>
<li>1996.11，网景公司向<code>ECMA（欧洲计算机制造商协会）</code>提交申请语言标准</li>
<li>1997.06，ECMA 以 JavaScript 为基础指定了 ECMAScript 标准规范<code>ECMA-262</code><ul>
<li>JavaScript 成为了 ECMAScript 标准规范最著名的实现语言之一</li>
<li>然后 ActionScript 和 JScript 也是 ECMAScript 标准的实现语言</li>
</ul>
</li>
</ul>
</li>
</ul>
<h4 id="JavaScript-与-ECMAScript-标准的关系"><a href="#JavaScript-与-ECMAScript-标准的关系" class="headerlink" title="JavaScript 与 ECMAScript 标准的关系"></a>JavaScript 与 ECMAScript 标准的关系</h4><ul>
<li>ECMAScript 是 JavaScript 的标准，描述了该语言的<code>语法</code>与<code>基本对象</code></li>
<li>JavaScript 是 ECMAScript 的实现之一，除了基本实现之外，JavaScript 还多了自己的<code>DOM，BOM</code>的操作</li>
</ul>
<h4 id="JavaScript-的特点"><a href="#JavaScript-的特点" class="headerlink" title="JavaScript 的特点"></a>JavaScript 的特点</h4><ul>
<li>按照运行方式不同，<ul>
<li><code>编译性语言</code>:C 语言&#x2F;C++ –预编译-编译-汇编–&gt; 等步骤<code>一次性</code>将代码转为(linux 或 window..的)二进制 –&gt; 执行</li>
<li><code>解释性语言</code>:JS&#x2F;Python –&gt; 一行行读取，一行行执行(JS 浏览器执行)</li>
<li><code>先编译再解释</code>:java 编译成 .class</li>
</ul>
</li>
<li>动静类型语言<ul>
<li><code>静态类型</code>：在代码执行之前，可以确定一个变量准确类型，并且之后不予许修改</li>
<li><code>动态类型</code>：不确定一个变量的准确类型，可以动态改变变量类型，灵活，但是不安全(JS 就是这种)</li>
</ul>
</li>
<li>js 的主要应用场景<ul>
<li>网页交互</li>
<li>服务端开放(NodeJs)</li>
<li>命令行工具(NodeJs)</li>
<li>桌面应用程序(VsCode 用 TypeScript 开法，GitHub 可以验证)</li>
<li>APP(React Native,uni 等)</li>
<li>游戏开发(cocos2d-js)</li>
<li>小程序开发</li>
</ul>
</li>
</ul>
<h4 id="JavaScript-编写位置"><a href="#JavaScript-编写位置" class="headerlink" title="JavaScript 编写位置"></a>JavaScript 编写位置</h4><ul>
<li>在 HTML 中直接执行</li>
</ul>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">onclick</span>=<span class="string">&quot;alert(&#x27;html执行js&#x27;)&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;javascript:alsert(&#x27;html执行js&#x27;)&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br></pre></td></tr></table></figure>

<ul>
<li>通过 script 标签执行</li>
<li>通过 script src 属性外部引入 JS 文件<ul>
<li>标签间不能写代码，并且要有双标签</li>
<li>由于文档是从上到下执行的，所以建议把标签放在主体内容后面</li>
<li>早期需要<code>type=&quot;text/javascriopt&quot;</code>这种,由于限制所以主流浏览器以及 html5 的默认脚本语言就是 JS,所以写 JS 代码的话不用写了</li>
<li>html 和 css 不区分大小写，js<code>严格区分</code></li>
</ul>
</li>
</ul>
<h4 id="注释"><a href="#注释" class="headerlink" title="注释"></a>注释</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span>js</span><br><span class="line"><span class="comment">// xxxxxx</span></span><br><span class="line"><span class="comment">/* xxxxxx */</span></span><br><span class="line"></span><br><span class="line">文档注释格式</span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> *  xxxxx</span></span><br><span class="line"><span class="comment"> *  xxxxx</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="number">2.</span>html</span><br><span class="line"><span class="comment">// &lt;!----&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="number">3.</span>css</span><br><span class="line"><span class="comment">/**/</span></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="有浏览器交互"><a href="#有浏览器交互" class="headerlink" title="有浏览器交互"></a>有浏览器交互</h4><ul>
<li>cosole.log()</li>
<li>alert()</li>
<li>document.write()</li>
<li>prompt(“请输入数据”)</li>
</ul>
<h4 id="如何定义变量"><a href="#如何定义变量" class="headerlink" title="如何定义变量"></a>如何定义变量</h4><ul>
<li><p>var 变量标识符 &#x3D; 值;</p>
</li>
<li><p>var a,b,c;</p>
</li>
<li><p>let、const、var</p>
</li>
<li><p>标识符</p>
<ul>
<li>数字、字母、_ 、$ (数字不能开头)</li>
<li>不能是关键字和保留字(保留字很多是其他语言拥有，js 暂未实现的标识符)</li>
</ul>
</li>
<li><p>命名规范以及主要事项</p>
<ul>
<li>小驼峰(多个单词，除第一个，后面的首字母大写)</li>
<li>驼峰(多个单词首字母大写)</li>
<li>见名知意</li>
<li>复制等号两边建议加空格(shell 强制不能加空格)</li>
</ul>
</li>
<li><p>交换两个值为数字的变量，不用第三个变量,可以用<code>加减</code>的方式实现</p>
</li>
</ul>
<h4 id="数据类型"><a href="#数据类型" class="headerlink" title="数据类型"></a>数据类型</h4><ul>
<li><p>引用数据类型:Object</p>
</li>
<li><p>特殊的引用构造类型:Function、Array、Regexp、Date、Math、Error、Math、Map、Set</p>
</li>
<li><p>基础类型:Number、String、Boolean、Null、Undefined、Symbol、Bigint</p>
<ul>
<li><p>数字:Number,值数字、NaN</p>
<ul>
<li>Number.MAX_VALUE 最大数值</li>
<li>Number.MIN_VALUE 最小数值</li>
<li>NaN:not a number，错误的数值运算返回</li>
<li>isNaN:判断是否不是一个数值</li>
</ul>
</li>
<li><p>字符串:String</p>
<ul>
<li><code>转义字符</code>：\n、\r、\t、\b 分别代表换行、回车、制表、退格<ul>
<li>开始的打字机换行需要消耗 0.2 秒时间，可以打印两个字符，要是在这 0.2 秒里面，又有新的字符传过来，那么这个字符将丢失。</li>
<li>在每行后面加两个表示结束的字符。一个叫做“回车”，告诉打字机把打印头定位在左边界；另一个叫做“换行”，告诉打字机把纸向下移一行</li>
<li>所以一行结尾是“&lt;回车&gt;&lt;换行&gt;”，即“\r\n”</li>
</ul>
</li>
</ul>
</li>
<li><p>Boolean:true&#x2F;false</p>
</li>
<li><p>Undefined(未定义):只有一个值 undefined；</p>
<ul>
<li>变量声明未赋值</li>
<li>函数为放回</li>
<li>对象属性未添加,等情况产生</li>
</ul>
</li>
<li><p>Null(空):只有一个值 null</p>
<ul>
<li>将变量指向这个<code>null</code>,那么如何原来那个对象没有句柄的话，回收机制就会进行回收,<code>起到销毁对象的作用</code></li>
</ul>
</li>
<li><p>Bigint：兼容性不好</p>
<ul>
<li>Number.MAX_SAFE_INTEGER 安全值之外的数运算可能失去精度 <code>9007199254740992 === 9007199254740993</code></li>
<li>创建BigInt数据，后面加n<ul>
<li><code>9007199254740992n === 9007199254740993n</code></li>
<li><code>BigInt(9007199254740992) === BigInt(9007199254740993)</code> ???</li>
</ul>
</li>
<li>注意点<ul>
<li>BigInt不支持一元加号运算符</li>
<li>不允许在bigint和 Number 之间进行混合操作</li>
<li>不能在JS内置函数中使用 <code>Math.max(2n, 4n, 6n);</code> xxx</li>
<li>if中不是 <code>0n</code> 就是 true</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>数据类型转换</p>
</li>
<li><p>方法</p>
<ul>
<li>typeof 返回类型字符串<ul>
<li>typeof age &#x2F;&#x2F; number</li>
<li>typeof str &#x2F;&#x2F; string</li>
</ul>
</li>
</ul>
</li>
<li><p>js 数据储存形式</p>
<ul>
<li>代码存储在硬盘，浏览器运行的时候会加载到<code>内存</code></li>
<li>内存空间<ul>
<li>栈空间(stack)<ul>
<li>申请变量空间&#x3D;基础数据类型值</li>
<li>申请变量空间&#x3D;引用数据类型地址</li>
</ul>
</li>
<li>堆空间<ul>
<li>用用数据类型数据</li>
</ul>
</li>
<li>销毁<ul>
<li>变量&#x3D;null</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>js 的二、八、十进制前缀</p>
<ul>
<li>0b、0o、0x</li>
</ul>
</li>
</ul>
<h4 id="检测数据类型"><a href="#检测数据类型" class="headerlink" title="检测数据类型"></a>检测数据类型</h4><ul>
<li><p>typeof</p>
<ul>
<li>检测 Array 等特殊构造类型都为<code>object</code><br><img src= "" data-lazy-src="/../../static/img/web-js1.png" alt="typeof"></li>
<li>可以判断处理 null 外的原始数据类型<ul>
<li>可能是 js 最初的 bug，为了兼容老代码一直保留</li>
</ul>
</li>
<li>只能判断对象类型中 Function</li>
<li>除此之外 typeof NaN 为 number</li>
</ul>
</li>
<li><p>instanceof</p>
<ul>
<li>检测某个构造行数的 prototype 属性是否出现在某个实例的原型链上(检测一个对象是否是某个构造函数的实例对象)<br><img src= "" data-lazy-src="/../../static/img/web-js2.png" alt="typeof"></li>
<li>由于可以随意更该原型指向，所以这个不安全</li>
<li>可以准确判断引用对象类型，不好判断原始类型<ul>
<li>Symbol.hasInstance 用于判断某对象是否为某构造器的实例。拿来自定义 instanceof 操作符在某个类上的行为。<br><img src= "" data-lazy-src="/../../static/img/web-js3.png" alt="typeof"></li>
</ul>
</li>
<li>实现 instanceof<br><img src= "" data-lazy-src="/../../static/img/web-js4.png" alt="typeof"></li>
</ul>
</li>
<li><p>constructor<br><img src= "" data-lazy-src="/../../static/img/web-js5.png" alt="typeof"></p>
<ul>
<li>返回构造函数</li>
<li>数值字面量如 1.constructor 直接使用会报错，需要通过(1).constructor 用()将数值转对象</li>
<li>处理 null 和 undefined，其他都比较可以检测</li>
<li>constructor 也可以手动修改，不安全</li>
</ul>
</li>
<li><p>Object.prototype.toString.call()<br><img src= "" data-lazy-src="/../../static/img/web-js6.png" alt="typeof"></p>
<ul>
<li>返回一个表示该对象的字符串</li>
<li>封装<br><img src= "" data-lazy-src="/../../static/img/web-js7.png" alt="typeof"><br><img src= "" data-lazy-src="/../../static/img/web-js8.png" alt="typeof"></li>
</ul>
</li>
</ul>
<h4 id="数据类型转换"><a href="#数据类型转换" class="headerlink" title="数据类型转换"></a>数据类型转换</h4><ul>
<li>转数值类型<ul>
<li>Number(a);<ul>
<li>数字字符串(正常),不是正常数字(NaN)</li>
<li>true&#x2F;false &#x3D;&gt; 1&#x2F;0</li>
<li>undefined&#x2F;null &#x3D;&gt; NaN&#x2F;0</li>
</ul>
</li>
<li>parseInt(str,radix 进制)&#x2F;parseFloat(str) ,合理运用编辑器代码提示<ul>
<li>将字符串转整型&#x2F;浮点型，只能是字符串</li>
<li>字符串有其他字符，取前面的数字(Number 直接 NaN)，第一个不是数字返回 NaN</li>
</ul>
</li>
</ul>
</li>
<li>转字符串<ul>
<li>num.toString()<ul>
<li>null、undefined、无 toString()</li>
</ul>
</li>
<li>String(num)<ul>
<li>null、undefined、布尔、数字等都可以</li>
</ul>
</li>
<li>num + “”:与字符串拼接</li>
</ul>
</li>
<li>转 bool(分支语句隐式调用 Boolean)<ul>
<li>Boolean(num)<br>false:””、0、-0、undefined、null、NaN<br>true:其他转字符串都为 true</li>
</ul>
</li>
</ul>
<h4 id="运算符"><a href="#运算符" class="headerlink" title="运算符"></a>运算符</h4><ul>
<li>算术运算符<ul>
<li>(加 正 字符串拼接)+、-、*、&#x2F;、%、++、–</li>
<li>自增自减++在前先加再用，++在后，先用再加</li>
</ul>
</li>
<li>赋值运算符<ul>
<li>&#x3D;、+&#x3D;、-&#x3D;、*&#x3D;、=、%&#x3D;</li>
</ul>
</li>
<li>逻辑运算符<ul>
<li>&amp;&amp;、||、！</li>
<li>断路运算-常用</li>
</ul>
</li>
<li>比较运算符<ul>
<li>&#x3D;&#x3D;、!&#x3D;、&gt;&#x3D;、&lt;&#x3D;、&lt;、&gt; (&#x3D;&#x3D; 的类型自动转换一般先转 number，再进行比较)</li>
<li>&#x3D;&#x3D;&#x3D;、!&#x3D;&#x3D; (严格相等比较，不会对比较的数据类型进行隐式转换,既比较类型也比较数据)</li>
</ul>
</li>
<li>优先级<ul>
<li><code>()</code> &gt; <code>++|--</code> &gt; <code>*|/|%</code> &gt; <code>位运算符的左右移</code> &gt; <code>非等判断</code> &gt; <code>等全等不等</code> ….</li>
<li><code>,</code> &lt; <code>赋值</code> &lt; <code>?:三元运算</code> &lt; 逻辑|| &lt; 逻辑&amp;&amp; &lt; 非左右移按位….</li>
</ul>
</li>
</ul>
<h3 id="执行语句"><a href="#执行语句" class="headerlink" title="执行语句"></a>执行语句</h3><blockquote>
<p>顺序(默认从上往下)、分支、循环的常用执行顺序<br>用{}包裹的代码，叫做<code>代码块</code></p>
</blockquote>
<h4 id="分支"><a href="#分支" class="headerlink" title="分支"></a>分支</h4><ul>
<li><code>if else</code></li>
<li><code>switch</code>:switch(exp){case “常量 1”:语句 1;break;…..;default:语句 n;}</li>
</ul>
<h4 id="循环"><a href="#循环" class="headerlink" title="循环"></a>循环</h4><ul>
<li><code>for</code></li>
<li><code>while(exp)&#123;&#125;</code>:条件为真一直循环执行</li>
<li><code>do...while</code></li>
<li><code>break，continue</code>：break 跳出整个循环(这个 for 或整个 while)，continue 跳出本次循环</li>
</ul>
<h3 id="数组"><a href="#数组" class="headerlink" title="数组"></a>数组</h3><h3 id="字符串"><a href="#字符串" class="headerlink" title="字符串"></a>字符串</h3><h3 id="重要概念"><a href="#重要概念" class="headerlink" title="重要概念"></a>重要概念</h3><p><code>事件循环 EventLoop</code>、</p>
<h2 id="JS-API"><a href="#JS-API" class="headerlink" title="JS API"></a>JS API</h2><blockquote>
<p>通过 JS 操作 html(DOM) 和 浏览器(BOM)</p>
</blockquote>
<h3 id="DOM"><a href="#DOM" class="headerlink" title="DOM"></a>DOM</h3><blockquote>
<p>dom 文档对象模型，操作网页内容，实现特效和交互</p>
</blockquote>
<ul>
<li><p>DOM 树对象(浏览器根据html标签生成的JS对象)</p>
<ul>
<li>DOM 树对象包含所有标签</li>
<li>修改某个对象属性会映射到所有标签上</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// querySelector(css选择器 button | .class | #id | ul li...); 返回第一个匹配的对象，没有返回null</span></span><br><span class="line"><span class="comment">// querySelectorAll 返回所有匹配 NodeList 伪数组(有长度、有索引、但是没有js pop push 等方法)</span></span><br><span class="line"><span class="keyword">let</span> div = <span class="variable language_">document</span>.<span class="title function_">querySelector</span>(<span class="string">&quot;div&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 修改内容</span></span><br><span class="line"><span class="variable language_">document</span>.<span class="title function_">write</span>(<span class="string">&quot;xxx&quot;</span>); <span class="comment">// 直接追加到文档</span></span><br><span class="line">div.<span class="property">innerHTML</span> = <span class="string">&quot;xxx&quot;</span>; <span class="comment">// 设置元素内容</span></span><br><span class="line">div.<span class="property">outerHTML</span> = <span class="string">&quot;&quot;</span>; <span class="comment">// 包括操作元素与元素内容</span></span><br><span class="line">div.<span class="property">innerText</span> = <span class="string">&#x27;xxx&#x27;</span>; <span class="comment">// 不识别标签</span></span><br><span class="line">div.<span class="property">title</span>=<span class="string">&#x27;xxx&#x27;</span>; <span class="comment">// 修改属性</span></span><br><span class="line">div.<span class="property">style</span>.<span class="property">background</span>=<span class="string">&quot;#f0f&quot;</span>; <span class="comment">//修改样式</span></span><br><span class="line">div.<span class="property">style</span>.<span class="property">backgroundColor</span>=<span class="string">&quot;#f0f&quot;</span>; <span class="comment">// 驼峰换横杆</span></span><br><span class="line"><span class="comment">// div.style.width 这种只能操作行内的样式 </span></span><br><span class="line"></span><br><span class="line">div.<span class="property">className</span>=<span class="string">&#x27;addClass&#x27;</span>; <span class="comment">//动态添加类 覆盖原有类名</span></span><br><span class="line">div.<span class="property">className</span>+=<span class="string">&quot; newclassName&quot;</span>; <span class="comment">// 不会被覆盖</span></span><br><span class="line"></span><br><span class="line">div.<span class="property">classList</span> <span class="comment">// 获取样式列表 </span></span><br><span class="line">div.<span class="property">classList</span>.<span class="title function_">add</span>(<span class="string">&quot;xxx&quot;</span>); <span class="comment">// 添加</span></span><br><span class="line">div.<span class="property">classList</span>.<span class="title function_">remove</span>(<span class="string">&quot;xxx&quot;</span>); <span class="comment">// 删除</span></span><br><span class="line">div.<span class="property">classList</span>.<span class="title function_">toggle</span>(<span class="string">&quot;xxx&quot;</span>); <span class="comment">// 切换</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// ========================================元素大小和位置 (三大家族 scroll offset client)</span></span><br><span class="line"><span class="comment">// scroll</span></span><br><span class="line">div.<span class="property">scrollWidth</span> <span class="comment">// 返回div内容的宽高(内部超过自己元素,或文本的宽高，div overflow:auto; 后拉动滚动条后可以看到的宽高)</span></span><br><span class="line">div.<span class="property">scrollHeight</span> </span><br><span class="line">div.<span class="property">scrollTop</span>  <span class="comment">// 向上滚动了的，看不见的大小，默认0，可赋值修改</span></span><br><span class="line">div.<span class="property">scrollLeft</span> <span class="comment">// 向右   最大的scrollLeft值 + 可见有内容的宽度 = div.scrollWidth</span></span><br><span class="line"><span class="variable language_">document</span>.<span class="property">documentElement</span>.<span class="property">scrollTop</span> <span class="comment">//整个文档滚动了的距离</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// offset</span></span><br><span class="line">div.<span class="property">offsetWidth</span>  <span class="comment">// 元素自己的宽高(包括 内容+填充+边框 和 滚动条)</span></span><br><span class="line">div.<span class="property">offsetHeight</span> </span><br><span class="line">div.<span class="property">offsetTop</span> <span class="comment">// 获取自己上面，距离最近一个有定位父级的高度， 都没有就以浏览器左上角为准</span></span><br><span class="line">div.<span class="property">offsetLeft</span></span><br><span class="line"><span class="comment">// 当document.xxx.scrollTop == 某个元素的 offsetTop 时，就是这个元素到顶的时候</span></span><br><span class="line"><span class="comment">// 与 window.outerWidth 类似</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// client</span></span><br><span class="line">div.<span class="property">clientWidth</span> <span class="comment">// 获取元素可见部分宽高(包括 padding-left + height + padding-right)</span></span><br><span class="line">div.<span class="property">clientHeight</span></span><br><span class="line">div.<span class="property">clientTop</span>  <span class="comment">// 返回的是元素上左边框的厚度（border）,无边框为0</span></span><br><span class="line">div.<span class="property">clientLeft</span></span><br><span class="line"><span class="comment">// 与 window.innerWidth 类似</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 表单操作</span></span><br><span class="line"><span class="keyword">let</span> btn = <span class="variable language_">document</span>.<span class="title function_">querySelector</span>(<span class="string">&quot;button&quot;</span>);</span><br><span class="line">btn.<span class="property">disabled</span> = <span class="literal">false</span>; <span class="comment">//禁用按钮</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>
</li>
<li><p>节点(DOM树每个DOM下的属性内容等都是节点)</p>
<ul>
<li>元素节点、属性节点、文本节点、空格换行…</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 元素节点(DOM树的每一个标签)操作</span></span><br><span class="line"><span class="comment">// 获取父节点</span></span><br><span class="line">eleNode.<span class="property">parentNode</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 获取子节点</span></span><br><span class="line">eleNodeParent.<span class="property">children</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 兄弟节点</span></span><br><span class="line">eleNode.<span class="property">nextElementSibling</span>  <span class="comment">//下一个节点</span></span><br><span class="line">eleNode.<span class="property">previousElementSibling</span> <span class="comment">// 上一个节点</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 创建元素节点</span></span><br><span class="line"><span class="keyword">let</span> div = <span class="variable language_">document</span>.<span class="title function_">createElement</span>(<span class="string">&quot;div&quot;</span>);</span><br><span class="line">div.<span class="property">className</span>=<span class="string">&quot;xxx&quot;</span>;</span><br><span class="line"></span><br><span class="line">eleNodeParent.<span class="title function_">appendChild</span>(div) <span class="comment">// 父元素最后最近新节点</span></span><br><span class="line">eleNodeParent.<span class="title function_">insertBefore</span>(div,parentDom) <span class="comment">//指定节点前插入  参数:新节点， 指定放在哪个节点前面</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 克隆节点</span></span><br><span class="line">eleNode.<span class="title function_">cloneNodew</span>(<span class="literal">true</span>)  <span class="comment">// 可溶一个一样的节点，参数true代表连后代节点一起克隆</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 删除节点</span></span><br><span class="line">eleNodeParent.<span class="title function_">removeChild</span>(eleNodeParent.<span class="property">children</span>[<span class="number">0</span>]) <span class="comment">//必先找到父节点，从父节点删除子节点</span></span><br></pre></td></tr></table></figure>


<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">-   事件</span><br><span class="line"></span><br><span class="line">    -   事件监听(绑定事件、注册事件)，监测程序是否有注册的事件发生，如果有就立即调用一个函数做出响应</span><br><span class="line"></span><br><span class="line">    ```javascript</span><br><span class="line">    // DOMLevel 0</span><br><span class="line">    // 相同事件会被覆盖，都是事件冒泡</span><br><span class="line">    // &lt;input type=&quot;button&quot; onclick=&quot;alert(0);&quot; /&gt;</span><br><span class="line">    ele.onclick = function()&#123;&#125;</span><br><span class="line">    ele.onclick = null; // 清理</span><br><span class="line">    </span><br><span class="line">    // DOMLevel 2</span><br><span class="line">    // 相同事件不会被覆盖，可设置捕获和冒泡</span><br><span class="line">    // 事件源 ele 、事件名 args[0] 、事件触发做的事情 args[1]</span><br><span class="line">    ele.addEventListener(&quot;event name&quot;,()=&gt;&#123;&#125;,bool); //bool 代表是否使用捕获机制，true 捕获 false 冒泡</span><br><span class="line">    ele.removeEventListenet(&quot;event name&quot;,&quot;函数名称&quot;,bool) // 清除事件，匿名函数无法被清除</span><br><span class="line">    // DOMLevel 3 一样的只是加了很多很多事件</span><br><span class="line">    </span><br><span class="line">    // 创建自定义事件（新）</span><br><span class="line">    const event = new Event(&#x27;build&#x27;);</span><br><span class="line">    // 添加 e 的属性</span><br><span class="line">    const event = new CustomEvent(&#x27;build&#x27;, &#123; detail: elem.dataset.time &#125;);</span><br><span class="line">    // 监听它</span><br><span class="line">    elem.addEventListener(&#x27;build&#x27;, (e) =&gt; &#123; /* … */ &#125;, false);</span><br><span class="line">    // 触发它</span><br><span class="line">    elem.dispatchEvent(event);</span><br><span class="line">    </span><br></pre></td></tr></table></figure>

<ul>
<li>事件对象</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 监听函数回调的第一个参数 e event ...</span></span><br><span class="line"><span class="comment"> * 包含与事件相关信息的对象</span></span><br><span class="line"><span class="comment"> * 常用属性 e. (不同事件 e的属性不一样)</span></span><br><span class="line"><span class="comment"> *      type：当前事件类型</span></span><br><span class="line"><span class="comment"> *      clientX/clientY：点击位置相对于浏览器可见窗口左上角的位置（显示位置不包括状态栏等）      </span></span><br><span class="line"><span class="comment"> *      pageX/pageY：点击位置相对于document文档左上角的位置(包括页面滚动的距离)      </span></span><br><span class="line"><span class="comment"> *      offsetX/offsetY：点击位置相对于当前点击的DOM元素左上角的位置      </span></span><br><span class="line"><span class="comment"> *      screenX/screenY：点击位置相对于设备屏幕的位置      </span></span><br><span class="line"><span class="comment"> *      layerX/layerY：点击位置，冒泡方向，有position定位元素，定位元素的 offsetX/offsetY 值,否则 == pageX/pageY</span></span><br><span class="line"><span class="comment"> *      movementX/movementY：鼠标移动的时候，这次相对上次移动的距离（移动慢基本是 0 1 -1 -2）</span></span><br><span class="line"><span class="comment"> *      tiltX/tiltY：指针（触控笔）的 XZ 平面与屏幕之间的角度,正值 向用户倾斜，不支持位0      </span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> *      key/code：获取检测操作的按键的值(以前的keyCode ascii码 废弃中)      </span></span><br><span class="line"><span class="comment"> *      </span></span><br><span class="line"><span class="comment"> *      </span></span><br><span class="line"><span class="comment"> */</span> </span><br><span class="line"></span><br></pre></td></tr></table></figure>

<ul>
<li>事件流</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 事件流指的是事件完整执行过程中的流动路径</span></span><br><span class="line"><span class="comment"> * 主要有两个阶段 事件捕获 和 事件冒泡 </span></span><br><span class="line"><span class="comment"> * 事件捕获 (参数三设置true)</span></span><br><span class="line"><span class="comment"> *    一个元 素事件被触发，先触发最父层，拥有该事件的元素</span></span><br><span class="line"><span class="comment"> *    document 开始 -&gt; html -&gt; body -&gt; 单前点击的元素      </span></span><br><span class="line"><span class="comment"> * 事件冒泡</span></span><br><span class="line"><span class="comment"> *    当一个元素事件被触发时，同样的事件会在该元素的祖先元素(父级、父父级。。document)依次触发，如果它们有监听这个事件的话</span></span><br><span class="line"><span class="comment"> *    当前点击元素  -&gt; body -&gt; html -&gt; document  </span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * 阻止事件流动 （事件冒泡，事件捕获）</span></span><br><span class="line"><span class="comment"> *    监听注册事件的时候，冒到这个元素的这个事件就会停止</span></span><br><span class="line"><span class="comment"> *    e.stopPropagation();</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * 鼠标移入依次事件</span></span><br><span class="line"><span class="comment"> *      mouseover 和 mouseout  这个移入移出默认有冒泡行为</span></span><br><span class="line"><span class="comment"> *      mouseenter 和 mouseleave  这个移入移出不会有冒泡行为</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * 阻止默认行为（阻止链接跳转，表单的默认就要的功能）</span></span><br><span class="line"><span class="comment"> *      e.preventDefault()</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * 事件流特性 实现事件委托</span></span><br><span class="line"><span class="comment"> *      给父级注册事件，父级收到点击的时候，通过 e.target 获取具体点击的子元素</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> */</span></span><br></pre></td></tr></table></figure>

<ul>
<li>常用事件</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 滚动事件 scroll</span></span><br><span class="line"><span class="variable language_">window</span> 或 ele.<span class="title function_">addEventListener</span>(<span class="string">&quot;scroll&quot;</span>,<span class="function">(<span class="params">e</span>)=&gt;</span>&#123;</span><br><span class="line">    </span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">// load 和 DOMContentLoaded (document 的 dom被解析后就直接触发 无需等待样式表、图片等加载完成)</span></span><br><span class="line"><span class="comment">// pageshow 事件在每次加载页面时触发，即 onload 事件在页面从浏览器缓存中读取时不触发。 </span></span><br><span class="line"><span class="comment">// resize 当窗口发生变化时触发</span></span><br><span class="line"><span class="comment">// contextmenu 右键触发</span></span><br><span class="line"><span class="comment">// hashchange 该事件在当前 URL 的锚部分发生修改时触发</span></span><br><span class="line"><span class="comment">// pagehide 该事件在用户离开当前网页跳转到另外一个页面时触发</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>环境对象 this</p>
<ul>
<li>非箭头函数 谁调用this指向谁</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// this 指向</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">fn</span>(<span class="params"></span>)&#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="title function_">fn</span>() == <span class="variable language_">window</span>.<span class="title function_">fn</span>() == <span class="variable language_">window</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> obj = &#123;</span><br><span class="line">    <span class="attr">fn</span>:<span class="keyword">function</span>(<span class="params"></span>)&#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">obj.<span class="title function_">fn</span>() == obj</span><br><span class="line"></span><br><span class="line"><span class="comment">// ele 被点击 this 是ele </span></span><br><span class="line">ele.<span class="title function_">addEventListener</span>(<span class="string">&quot;click&quot;</span>,<span class="keyword">function</span>(<span class="params"></span>)&#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>)</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 面向对象</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">Obje</span>(<span class="params"></span>)&#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>,<span class="string">&#x27;default&#x27;</span>) <span class="comment">// Obje &#123;&#125;</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">showthis</span> = <span class="keyword">function</span>(<span class="params"></span>)&#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>,<span class="string">&#x27;showthis&#x27;</span>) <span class="comment">// Obje &#123;&#125;</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="title class_">Obje</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">showprotothis</span> = <span class="keyword">function</span>(<span class="params"></span>)&#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>,<span class="string">&#x27;showprotothis&#x27;</span>) <span class="comment">// Obje &#123;&#125;</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> sobj = <span class="keyword">new</span> <span class="title class_">Obje</span>();</span><br><span class="line"></span><br><span class="line"><span class="comment">// call</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">testCall</span>(<span class="params"></span>)&#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>)  <span class="comment">// Obje &#123;&#125;</span></span><br><span class="line">&#125;</span><br><span class="line">testCall.<span class="title function_">call</span>(<span class="title class_">Obje</span>)</span><br><span class="line"></span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="BOM"><a href="#BOM" class="headerlink" title="BOM"></a>BOM</h3><blockquote>
<p>浏览器对象模型 ,最顶级 window 对象</p>
</blockquote>
<p>window 常见方法</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// window 的方法 都可以省略 window.</span></span><br><span class="line"><span class="comment">// setInterval alter addEventListener requestAnimationFrame 全局函数...</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 定时器</span></span><br><span class="line"><span class="variable language_">window</span>.<span class="property">setInterval</span></span><br><span class="line"><span class="variable language_">window</span>.<span class="property">clearInterval</span></span><br><span class="line"><span class="variable language_">window</span>.<span class="property">setTimeout</span></span><br><span class="line"><span class="variable language_">window</span>.<span class="property">clearTimeout</span></span><br><span class="line"><span class="variable language_">window</span>.<span class="property">requestAnimationFrame</span> <span class="comment">// 也是一个时间内调用此次回调函数，只是它的时间是系统决定的，不是用户决定的</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 本地存储</span></span><br><span class="line"><span class="comment"> * 将数据存储在浏览器中，刷新或关闭浏览器都可以保留数据</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * localStorage 5M 左右</span></span><br><span class="line"><span class="comment"> *      生命周期永久存在，除非手动删除，或 或特殊浏览器(chromeium 就没办法保留)</span></span><br><span class="line"><span class="comment"> *      相同浏览器 相同站点多页面共享</span></span><br><span class="line"><span class="comment"> *      键值对方式储存</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"> <span class="variable language_">localStorage</span>.<span class="title function_">setItem</span>(key,value) <span class="comment">// 添加普通数据</span></span><br><span class="line"> <span class="variable language_">localStorage</span>.<span class="title function_">setItem</span>(key,<span class="title class_">JSON</span>.<span class="title function_">stringify</span>(<span class="title class_">Obj</span>)) <span class="comment">// 添加对象数据</span></span><br><span class="line"> <span class="variable language_">localStorage</span>.<span class="title function_">getItem</span>(key) <span class="comment">// 获取普通数据</span></span><br><span class="line"> <span class="title class_">JSON</span>.<span class="title function_">parse</span>(<span class="variable language_">localStorage</span>.<span class="title function_">setItem</span>(key)) <span class="comment">// 获取对象数据</span></span><br><span class="line"> <span class="variable language_">localStorage</span>.<span class="title function_">removeItem</span>(key) <span class="comment">// 删除</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// sessionStorage  临时储存，关闭浏览器数据消失</span></span><br></pre></td></tr></table></figure>

<p>window 主要包含模块</p>
<ul>
<li>document (网页文档)<ul>
<li>JS 执行机制</li>
<li><code>document.execCommand(&#39;copy&#39;)</code> 复制文档中选中的内容</li>
<li><code>document.activeElement</code> 获取操作页面上聚焦的元素，默认body</li>
<li><code>document.designMode=on</code> 设置文档可编辑 ，设置为设计模式，所有功能失效</li>
</ul>
</li>
<li>location 对象<ul>
<li>URL相关的操作</li>
<li>location.reload(true) 刷新页面，true &#x3D;&#x3D; Ctrl + F5</li>
</ul>
</li>
<li>navigator 对象<ul>
<li>浏览器相关信息</li>
<li>navigator.clipboard 替代即将废弃的 <code>document.execCommand</code></li>
</ul>
</li>
<li>history 对象<ul>
<li>浏览器的前进&#x2F;后退&#x2F;上个页面 forward() 、back() 、go(-1)</li>
</ul>
</li>
<li>screen</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 设备显示屏的宽高</span></span><br><span class="line">screen.<span class="property">width</span></span><br><span class="line">screen.<span class="property">height</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 浏览器最大化后的宽高 与 距离上左的距离</span></span><br><span class="line">screen.<span class="property">availWidth</span></span><br><span class="line">screen.<span class="property">availHeight</span></span><br><span class="line">screen.<span class="property">availTop</span></span><br><span class="line">screen.<span class="property">availLeft</span></span><br><span class="line"></span><br><span class="line">screen.<span class="property">availHeight</span> + screen.<span class="property">availTop</span> == screen.<span class="property">height</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<ul>
<li>其他 window 属性</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">screenLeft/screenX <span class="comment">// 窗口距离设备左边的距离</span></span><br><span class="line">screenTop/screenY <span class="comment">// 窗口距离设备上边的距离</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>



<h2 id="JS-高级"><a href="#JS-高级" class="headerlink" title="JS 高级"></a>JS 高级</h2><blockquote>
<p>  项目实践 <code>lzo-web-project</code> 下 <code>ECMAScript</code> 下的 <strong>JS高级</strong></p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://www.ecma-international.org/publications-and-standards/standards/">ecma 标准</a></p>
<h3 id="JavaScript-的-this"><a href="#JavaScript-的-this" class="headerlink" title="JavaScript 的 this"></a>JavaScript 的 this</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 四种影响this的因素</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">fn</span>(<span class="params"></span>)&#123; <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>) &#125;</span><br><span class="line"><span class="comment">// 默认绑定 window 为 this，直接调用</span></span><br><span class="line"><span class="title function_">fn</span>()</span><br><span class="line"></span><br><span class="line"><span class="comment">// 隐式绑定，调用对象obj 为 this，通过对象调用</span></span><br><span class="line">obj.<span class="title function_">fn</span>()</span><br><span class="line"></span><br><span class="line"><span class="comment">// 显示绑定 call/apply/bind 强制绑定目标</span></span><br><span class="line">fn.<span class="title function_">call</span>(&#123;&#125;,<span class="string">&#x27;a&#x27;</span>,<span class="string">&#x27;b&#x27;</span>)</span><br><span class="line">fn.<span class="title function_">apply</span>(&#123;&#125;,[<span class="string">&#x27;a&#x27;</span>,<span class="string">&#x27;b&#x27;</span>])</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> fnb = fn.<span class="title function_">bind</span>(&#123;&#125;,<span class="string">&#x27;a&#x27;</span>,<span class="string">&#x27;b&#x27;</span>) <span class="comment">// 得到一个新的，绑定好指定this指向的函数</span></span><br><span class="line"><span class="title function_">fnb</span>(<span class="string">&#x27;a&#x27;</span>,<span class="string">&#x27;b&#x27;</span>) <span class="comment">// this指向 &#123;&#125;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// new 绑定,构造函数的this指向new时创建的空对象</span></span><br><span class="line"><span class="keyword">let</span> nfn = <span class="keyword">new</span> <span class="title function_">fn</span>()</span><br><span class="line"></span><br><span class="line"><span class="comment">// 箭头函数无this，只会使用上级作用域的this，call/apply/bind 对它无效，隐式绑定对它也无效</span></span><br></pre></td></tr></table></figure>

<h3 id="浏览器的运行原理"><a href="#浏览器的运行原理" class="headerlink" title="浏览器的运行原理"></a>浏览器的运行原理</h3><h4 id="通过URL拿到资源"><a href="#通过URL拿到资源" class="headerlink" title="通过URL拿到资源"></a>通过URL拿到资源</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">1、输入网站</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">2、解析域名（DNS解析） 得到域名对应主机的IP地址</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">3、连接主机，通过用户访问的端口、路径返回对应资源到浏览器</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">4、浏览器得到返回的页面(index.html)</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">6、运行index.html  =&gt; 遇到<span class="built_in">link</span>下载css =&gt; 遇到script下载js并执行（阻塞无法构建DOM tree） =&gt; 遇到图片下载 ...</span></span><br></pre></td></tr></table></figure>

<h4 id="浏览内核"><a href="#浏览内核" class="headerlink" title="浏览内核"></a>浏览内核</h4><blockquote>
<p>  常见的<strong>浏览器内核</strong>&#x2F;<strong>浏览器引擎</strong>&#x2F;<strong>渲染引擎</strong></p>
</blockquote>
<p><img src= "" data-lazy-src="/../..%5Cstatic%5Cimg%5C2023-03-03_182155.jpg"></p>
<h4 id="页面渲染详细流程"><a href="#页面渲染详细流程" class="headerlink" title="页面渲染详细流程"></a>页面渲染详细流程</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">浏览器拿到index.html</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">遇到引入css，下载css，解析css ，不阻塞继续解析html，形成 DOM tree (之后JS可能进行DOM操作)</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">解析CSS，形成 CSSOM Tree(CSS 对象模型 Style Rules)</span> </span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">合并 DOM tree 和 Style Rules，生成渲染树 Render Tree</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">在 Render Tree 上进行 Layout 布局（确定宽高和位置信息）</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">		当页面DOM位置变化，宽高方式变化也会重新 布局 Render Tree (称为 回流)</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">进行 Painting 绘制 （样式发生变化 会来到 Painting 进行 重绘）</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">进行 Display 显示</span></span><br></pre></td></tr></table></figure>

<p><img src= "" data-lazy-src="/../..%5Cstatic%5Cimg%5C2023-03-03_183614.jpg"></p>
<blockquote>
<p>  引起回流的场景（reflow）</p>
</blockquote>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">DOM 结构发生改变，添加移除移动节点</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">部分发生改变（widht height padding font-size 等）</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">窗口 resize 等</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">...</span></span><br></pre></td></tr></table></figure>

<blockquote>
<p>  重绘 （repaint）</p>
</blockquote>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">第一次渲染内容叫绘制（paint）</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">之后，页面颜色所有颜色发生改变，边框样式发生改变就会发生重绘</span></span><br></pre></td></tr></table></figure>

<blockquote>
<p>  回流一定包含重绘，重绘不一定包含回流，避免回流方法</p>
</blockquote>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">修改样式时尽量已持续修改，（通过class修改，好了一次性添加到dom上）</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">避免评分操作DOM（用 DocumentFragment 一次性操作）</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">对一些元素使用绝对定位，时回流的范围减小（脱离文档流）</span></span><br></pre></td></tr></table></figure>

<h4 id="特殊解析-composite-合成"><a href="#特殊解析-composite-合成" class="headerlink" title="特殊解析 composite 合成"></a>特殊解析 composite 合成</h4><blockquote>
<p>  浏览器渲染的优化手段</p>
</blockquote>
<p>默认情况，前面是一个<strong>标准流</strong>的<strong>渲染流程</strong>，标准流的内容会被绘制在**一个图层(Layer)**中 （控制台找到更多工具 找到 layers 可查看）</p>
<p>特殊属性（如：定位）会创建一个<strong>新的单独的合成层</strong>（<code>CompositingLayer</code>），并且新的图层可以利用<strong>GPU来加速绘制</strong></p>
<ul>
<li>每个合成层都是单独渲染的，不会影响标准流<ul>
<li>3D transforms，</li>
<li>transition过度过程中，如果元素用 transform 做动画，会形成新图层，提高效率</li>
<li>video、canvas、iframe </li>
<li>position：fixed ( 形成一个新的Layer ，absolute 只会脱标，不会新城合成层) </li>
<li>给元素添加属性 will-change ，那么这个元素产生动画，也会分层</li>
</ul>
</li>
<li>新图层提高性能是需要 <strong>消耗硬件资源</strong>的，所有不能滥用</li>
</ul>
<h4 id="Script-元素的优化"><a href="#Script-元素的优化" class="headerlink" title="Script 元素的优化"></a>Script 元素的优化</h4><blockquote>
<p>  因为 JS 需要经常操作 DOM ，防止过度重绘回流，渲染时遇到 JS 默认会先执行完成再继续，所以JS放前面会阻塞页面渲染</p>
</blockquote>
<p><code>script</code> 属性 <code>defer</code> 和 <code>async</code></p>
<h5 id="defer-属性"><a href="#defer-属性" class="headerlink" title="defer 属性"></a>defer 属性</h5><blockquote>
<p>  当浏览器遇到defer 属性的 <strong>script 文件</strong>，会先对立下载页面，等待DOM Tree 构建完成，再执行script</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">&lt;head&gt;</span><br><span class="line">    <span class="language-xml"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./js/test.js&quot;</span> <span class="attr">defer</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span></span><br><span class="line">	<span class="language-xml"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./js/demo.js&quot;</span> <span class="attr">defer</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span>    </span><br><span class="line">&lt;/head&gt;</span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span>app<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;box&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;title&quot;</span>&gt;</span>title<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;nav&quot;</span>&gt;</span>nav<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;product&quot;</span>&gt;</span>product<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">    <span class="comment">&lt;!-- 1.下载需要很长的事件, 并且执行也需要很长的时间 --&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="comment">&lt;!-- 总结一: 加上defer之后, js文件的下载和执行, 不会影响后面的DOM Tree的构建 --&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="comment">&lt;!-- 总结二: 如果脚本提前下载好了，也会等待DOM Tree 构建完毕，在DOMContentLoaded 事件之前先执行defer中的代码 --&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="comment">// 总结三: defer代码是在DOMContentLoaded事件发出之前执行</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="variable language_">window</span>.<span class="title function_">addEventListener</span>(<span class="string">&quot;DOMContentLoaded&quot;</span>, <span class="function">() =&gt;</span> &#123;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;success&quot;</span>);</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">    &#125;);</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;<span class="name">h1</span>&gt;</span>哈哈哈哈啊<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 如果多个defer的script文件，浏览器会保证安装编写的顺序依次执行</span></span><br><span class="line"><span class="comment">// 执行书序  直接下载两个js文件/同时展示页面，包括 最后的h1 =&gt; DOM Tree 构建完成 =&gt; 依次执行外部脚本 =&gt; 打印 success</span></span><br></pre></td></tr></table></figure>

<h5 id="async-属性"><a href="#async-属性" class="headerlink" title="async 属性"></a>async 属性</h5><blockquote>
<p>  让脚本不阻塞页面，让脚本完全独立，独立下载、独立运行、不会等待其他脚本、不能保证在 DOM Tree 构建后执行</p>
</blockquote>
<h3 id="JS-引擎"><a href="#JS-引擎" class="headerlink" title="JS 引擎"></a>JS 引擎</h3><blockquote>
<p>  前面只提到下载执行阻塞 JavaScript 代码，没有说的<strong>具体执行过程</strong></p>
</blockquote>
<p>浏览器内核（webkit）由 <code>WebCore</code> 和 <code>JavaScriptCore (JSCore JS引擎)</code> 两部分组成</p>
<p><img src= "" data-lazy-src="/../..%5Cstatic%5Cimg%5C2023-03-04_090139.jpg"></p>
<h4 id="V8引擎执行原理"><a href="#V8引擎执行原理" class="headerlink" title="V8引擎执行原理"></a>V8引擎执行原理</h4><ul>
<li><p><a target="_blank" rel="noopener" href="https://v8.dev/">V8 引擎</a>是<strong>blink</strong>浏览器内核的<strong>内置 JS引擎</strong> </p>
</li>
<li><p>Google 开源，C++ 编写，主要用于<code>Chrome</code> 和 <code>Node.js</code></p>
</li>
<li><p>V8 引擎可以<strong>独立运行</strong>，也可以其他任何程C++序中 </p>
</li>
<li><p>V8 的工作流程</p>
</li>
</ul>
<p><img src= "" data-lazy-src="/../..%5Cstatic%5Cimg%5C2023-03-04_100733.jpg"></p>
<p>将后 <strong>js 源码</strong>通过 <strong>Parse</strong> 解析成 <strong>AST抽象语法树</strong>，通过 <strong>lgnition</strong> 转化为cpu认识的<strong>字节码bytecode</strong> 给cpu运行</p>
<h4 id="V8核心概念"><a href="#V8核心概念" class="headerlink" title="V8核心概念"></a>V8核心概念</h4><h5 id="Parse-解析模块"><a href="#Parse-解析模块" class="headerlink" title="Parse 解析模块"></a>Parse 解析模块</h5><blockquote>
<p>  将 JavaScript 执行到的代码转化成 <strong>AST 抽象语法树</strong>，<strong>lgnition</strong> 解释器并不认识js源码</p>
<p>  词法分析(Scanner) &#x3D;&gt; 分词记号化(大量 tokens)  &#x3D;&gt; 一部分直接解析(parser) &#x2F; 一部分进行与解析(pre-parser)  &#x3D;&gt; 得到一个个Node节点 &#x3D;&gt; 得到 AST抽象语法树</p>
</blockquote>
<h5 id="lgnition-解释器"><a href="#lgnition-解释器" class="headerlink" title="lgnition 解释器"></a>lgnition 解释器</h5><blockquote>
<p>  将 <code>AST</code> 转换成 <code>bytecode</code> 字节码</p>
<p>  同时收集<strong>TurboFan优化</strong>所需要的信息，函数只调用一次，直接解释和执行 <code>bytecode</code></p>
<p>  函数调用多次，会别标记为<strong>热点函数</strong>，下次就会直接通过 <code>TurboFan</code> 转换成<strong>优化</strong>的<strong>机器码</strong>，<strong>提高</strong>执行性能</p>
</blockquote>
<h5 id="TurboFan-编译器"><a href="#TurboFan-编译器" class="headerlink" title="TurboFan 编译器"></a>TurboFan 编译器</h5><blockquote>
<p>  可以将收集到的（标记为热点函数的）字节码直接编译为 CPU 直接执行的<strong>机器码</strong></p>
<p>  后续<strong>热点函数</strong>执行的<strong>参数等因素</strong>发生变化，<strong>机器码</strong>会被还原成 <strong>字节码</strong>，<strong>降低</strong>执行性能</p>
</blockquote>
<h5 id="垃圾回收模块"><a href="#垃圾回收模块" class="headerlink" title="垃圾回收模块"></a>垃圾回收模块</h5><p>。。。</p>
<h3 id="浏览器中-JS-的运行原理"><a href="#浏览器中-JS-的运行原理" class="headerlink" title="浏览器中 JS 的运行原理"></a>浏览器中 JS 的运行原理</h3><h4 id="初始化全局对象"><a href="#初始化全局对象" class="headerlink" title="初始化全局对象"></a>初始化全局对象</h4><ul>
<li>js 引擎在执行代码<strong>之前</strong>，会在<strong>堆内存中</strong>创建一个<strong>全局对象</strong>：<code>Global Object(Go)</code></li>
<li>GO对象 所有<strong>作用域（scopt）</strong>都可以访问</li>
<li>里面包含 <code>Date</code>、<code>Array</code>、<code>String</code>、<code>Number</code>、<code>Math</code>、<code>setTimeout</code>、<code>setInterval</code> 这些全局函数</li>
<li>还有一个<strong>window 属性</strong>指向自己</li>
</ul>
<h4 id="执行上下文栈（ECS）"><a href="#执行上下文栈（ECS）" class="headerlink" title="执行上下文栈（ECS）"></a>执行上下文栈（ECS）</h4><blockquote>
<p>  就是执行代码的调用栈 （Execution Context Stack ECS），代码都是要在执行上下文栈中执行的</p>
</blockquote>
<h5 id="执行上下文"><a href="#执行上下文" class="headerlink" title="执行上下文"></a>执行上下文</h5><ul>
<li><p>接下来开始执行<strong>全局代码</strong></p>
<ul>
<li><p>需要构建一个 <strong>全局执行上下文</strong><code>Global Execution Context（GEC）</code> 来执行<strong>js引擎翻译好的</strong> -<strong>全局代码</strong>  </p>
</li>
<li><p><strong>全局执行上下文</strong> 会<strong>最先</strong>放入到 <strong>执行上下文栈</strong>中，处于最底部</p>
</li>
<li><p>调用函数，或es6的代码块，这些<strong>活跃的，局部的，执行执行上下文</strong>，依次压入，叠加，就形成了<strong>栈结构</strong>，先进后出</p>
<ul>
<li>函数执行上下文（FEC）</li>
</ul>
</li>
<li><p>最上面的永远是正则被执行的 <strong>执行上下文</strong>，执行完成，从<strong>栈顶出栈</strong></p>
</li>
</ul>
</li>
</ul>
<h5 id="执行上下文的-VO-详解"><a href="#执行上下文的-VO-详解" class="headerlink" title="执行上下文的 VO 详解"></a>执行上下文的 VO 详解</h5><blockquote>
<p>  每个执行上下文，都有一个自己<strong>保存变量的地方</strong>，让用户获取使用</p>
</blockquote>
<ul>
<li><strong>js 引擎翻译解析</strong>代码，<strong>开始执行前</strong>，<strong>变量</strong>放到内存中的<strong>执行上下文</strong>的细节<ul>
<li>每一个<strong>执行上下</strong>文会关联一个<strong>VO ( Variable Object 变量对象 ) <strong>，用来存放</strong>变量和函数</strong>声明<ul>
<li>代码永远是在执行上下文执行的，基本类型数据也是存在<strong>栈内存</strong>中，只是在 VO 对象属性中<strong>额外保存</strong>相应变量值</li>
</ul>
</li>
<li><strong>全局执行上下文</strong>的 <strong>VO</strong> 就是 堆内存<strong>GO</strong> 就是 **window  对象 **<ul>
<li>每次函数<strong>调用</strong>，创建新的 <strong>FEC</strong>，创建AO关联，函数执行上下文的 VO 是堆内存的<strong>AO (Activation Object 活跃的)</strong></li>
<li>初始化 argument，将<strong>参数作为变量存入AO中</strong></li>
<li>这个 AO 会作为函数执行上下文的 VO  来初始化变量</li>
<li>函数执行完毕，该函数的 FEC 出栈，AO 对象失去了句柄，在堆内存中游离，等待回收机制处理</li>
</ul>
</li>
<li>var变量放到执行上下文，默认值是 undefined</li>
<li>函数提前 放到执行上下文，默认值是一个内存地址，指向创建好的函数位置（所以函数可以在定义位置之前执行）<ul>
<li>只有最外层，能碰到的函数会预先创建</li>
</ul>
</li>
</ul>
</li>
</ul>
<h5 id="执行上下文的作用域链"><a href="#执行上下文的作用域链" class="headerlink" title="执行上下文的作用域链"></a>执行上下文的作用域链</h5><blockquote>
<p>  涉及变量的查找，就会用到 作用域  （scope）</p>
</blockquote>
<p>每一个<strong>执行上下文</strong>自己关联变量的 VO对象</p>
<blockquote>
<p>  作用域链 （scope chain） </p>
</blockquote>
<ul>
<li>行数<strong>创建的时候</strong>，就已经<strong>确定了自己的作用域链</strong>，与定义位置有关，与执行位置无关<ul>
<li>通过debugger ，sources，找到 witch，添加监视的函数名，找到 <code>[[Scopes]]</code> </li>
<li>浏览器有优化，如果没有使用某个上层作用域的变量，这边是看不到的</li>
</ul>
</li>
<li>每创建一个函数执行上下文，都会拿到函数定义就确定的<strong>作用域链</strong>（<code>scope chain</code>）<ul>
<li>作用域链是一个存放VO的列表（定义位置上下文的VO ~ 全局上下文的VO），根据<strong>代码类型</strong>初始化一系类数据</li>
<li>当使用一个变量标识符时，现在自己的作用域查找，找不到，才会去作用域链依次查找</li>
</ul>
</li>
</ul>
<h5 id="闭包"><a href="#闭包" class="headerlink" title="闭包"></a>闭包</h5><blockquote>
<p>  作用域链的特性，作用域链与<strong>定义位置</strong>有关，是形成闭包的最大因素</p>
</blockquote>
<ul>
<li><p>闭包实际上是一个 <strong>函数和一个关联的环境</strong> 组成的 <strong>结构体</strong></p>
</li>
<li><p>跟函数的最大差别是，当捕捉闭包的时候，他的 <strong>自由变量</strong> 会在<strong>捕捉时被确定</strong>，这样既<strong>脱离了原先的上下文</strong>，也能<strong>照常运行</strong></p>
</li>
<li><p>每创建一个函数时，闭包就被创建了</p>
</li>
<li><p>js 中一个普通函数 function，如果他可以访问外层作用域的自由变量，那么这个函数的周围环境就是一个闭包</p>
<ul>
<li>广义上说：JavaScript 中的函数都是闭包</li>
<li>狭义上说：JavaScript 中的函数，如果<strong>访问了外层作用域的变量</strong>，那么就是一个闭包</li>
</ul>
</li>
</ul>
<blockquote>
<p>  闭包的运用</p>
</blockquote>
<ul>
<li>运用案例一：默认情况，函数中通过参数，直接使用外部变量</li>
<li>运用案例二：定义<strong>外层函数</strong>内部<strong>定义并返回新函数</strong>，我们拿到<strong>内层函数</strong> 对<strong>外层函数参数或变量</strong>的<strong>任意使用</strong>的过程 <ul>
<li>返回就是为了把内部函数地址储存到外面去，否则是没办法使用的，也是一个无用的闭包</li>
<li>地址存到变量，比如全局 <strong>addr</strong>，就会存到 GO，根据<strong>可达性</strong>，GO 可以从addr找到<strong>返回的函数</strong>，<strong>返回的函数</strong>使用了外部函数变量，外部函数的AO，就可以从[[Scoops]]找到<strong>外部函数的AO</strong>，那么程序没结束，内部函数，和外部函数的AO对象就不会销毁</li>
<li>多次调用外层函数获得内存函数，会产生保留<strong>多个不同的AO</strong>，所有它们不冲突</li>
</ul>
</li>
<li>运用案例三：<strong>柯里化函数</strong></li>
</ul>
<blockquote>
<p>  内存泄漏 </p>
</blockquote>
<p>以上面<strong>案例二</strong>为例，我们得到了内部函数地址，储存到<strong>全局的addr中</strong>，关联这这个<strong>addr和它作用域链的AO对象</strong></p>
<p>如果后期永远不用这个<strong>addr</strong>，而<strong>垃圾回收GC</strong>根据可达性，不知道我们不用，不进行回收，这种情况就是<strong>内存泄漏</strong></p>
<p>可以通过 <strong>addr &#x3D; null</strong> 手动释放</p>
<p><strong>addr</strong> 关联的这个<strong>闭包</strong>里面用很多OA对象数据 ，如果不手动释放，就对内存很有压力，所以<strong>说闭包容易尝试内存泄漏</strong></p>
<p>普通表达式函数，</p>
<h5 id="执行上下文的-This"><a href="#执行上下文的-This" class="headerlink" title="执行上下文的 This"></a>执行上下文的 This</h5><h4 id="内存管理与垃圾回收"><a href="#内存管理与垃圾回收" class="headerlink" title="内存管理与垃圾回收"></a>内存管理与垃圾回收</h4><blockquote>
<p>  不管怎么方式管理内存，都会有几个生命周期</p>
</blockquote>
<ul>
<li>申请需要的内存</li>
<li>使用分配的内存</li>
<li>不需要时，释放内存空间<ul>
<li>手动管理：C、C++ 需要手动管理内存，通过调用API申请释放内存</li>
<li>自动管理：Java、JavaScript、Python 等都会自动管理内存</li>
</ul>
</li>
</ul>
<h5 id="js的垃圾回收"><a href="#js的垃圾回收" class="headerlink" title="js的垃圾回收"></a>js的垃圾回收</h5><blockquote>
<p>  JavaScript 的垃圾回收机制 （Garbage Collection）GC</p>
</blockquote>
<p> 对于<strong>不再使用的对象</strong>，我们都称之为<strong>垃圾</strong>，它需要被<strong>回收</strong>，以释放更多的内存空间</p>
<blockquote>
<p>   常见的GC算法</p>
</blockquote>
<p>1、V8 使用标记清除算法（mark-Sweep）</p>
<ul>
<li>核心思路<strong>可达性（Reachability）</strong></li>
<li>首先需要一个<strong>根对象</strong>，回收器会<strong>定期从根对象开始</strong>，找所有<strong>能引用到的对象</strong>进行<strong>标记</strong>，那些<strong>没有引用到</strong>的对象，就是<strong>不可用</strong>的</li>
<li>js 中根对象就是 GO window</li>
<li>怎么找才是难的</li>
</ul>
<p> V8 对标记清除算法的一些优化</p>
<ul>
<li>标记整理<ul>
<li>如果清除了13579位置的内存空间，下次需要一个较大的空间，这些位置<strong>还是不能用</strong></li>
<li><strong>标记整理</strong>会将，保留的02468位置，<strong>搬运汇集</strong>到<strong>连续的内存</strong>中，避免<strong>碎片化</strong></li>
</ul>
</li>
<li>分代收集<ul>
<li>将新创建的对象放一起，老旧放一起，新的多检查，老的稳定可以减少检测频次</li>
</ul>
</li>
<li>增量收集</li>
<li>闲时收集</li>
</ul>
<p>2、引用计数，遛狗法则（Reference counting），js不用这个</p>
<p>实时计算有<strong>多少个东西</strong>在引用某个<strong>空间的对象</strong>，多一个+1，少一个-1，引用某个对象的<strong>引用数量为0</strong>，就能销毁</p>
<h3 id="手写-call-apply-bind"><a href="#手写-call-apply-bind" class="headerlink" title="手写 call-apply-bind"></a>手写 call-apply-bind</h3> <figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> name = <span class="string">&quot;window&quot;</span>;</span><br><span class="line"><span class="keyword">var</span> ob = &#123;</span><br><span class="line">    <span class="attr">name</span>: <span class="string">&quot;obj&quot;</span>,</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">getName</span>(<span class="params">age</span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(age);</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>.<span class="property">name</span>);</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="title class_">Function</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">MyCall</span> = <span class="keyword">function</span> (<span class="params">obj, ...args</span>) &#123;</span><br><span class="line">    obj = obj == <span class="literal">null</span> || obj == <span class="literal">undefined</span> ? <span class="variable language_">window</span> : <span class="title class_">Object</span>(obj);</span><br><span class="line">    obj.<span class="property">fn</span> = <span class="variable language_">this</span>; <span class="comment">// 这样简洁，但是用户到时会看到fn函数</span></span><br><span class="line">    obj.<span class="title function_">fn</span>(...args);</span><br><span class="line">&#125;;</span><br><span class="line"><span class="title class_">Function</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">MyApply</span> = <span class="keyword">function</span> (<span class="params">obj, args</span>) &#123;</span><br><span class="line">    obj = obj == <span class="literal">null</span> || obj == <span class="literal">undefined</span> ? <span class="variable language_">window</span> : <span class="title class_">Object</span>(obj);</span><br><span class="line">    obj.<span class="property">fn</span> = <span class="variable language_">this</span>;</span><br><span class="line">    obj.<span class="title function_">fn</span>(...args);</span><br><span class="line">&#125;;</span><br><span class="line"><span class="title class_">Function</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">MyBind</span> = <span class="keyword">function</span> (<span class="params">obj, ...beforeArgs</span>) &#123;</span><br><span class="line">    obj = obj == <span class="literal">null</span> || obj == <span class="literal">undefined</span> ? <span class="variable language_">window</span> : <span class="title class_">Object</span>(obj);</span><br><span class="line">    obj.<span class="property">fn</span> = <span class="variable language_">this</span>;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">function</span> (<span class="params">...afterArgs</span>) &#123;</span><br><span class="line">        <span class="keyword">let</span> args = [...beforeArgs, ...afterArgs];</span><br><span class="line">        obj.<span class="title function_">fn</span>(...args);</span><br><span class="line">    &#125;;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">getName.<span class="title class_">MyCall</span>(ob, <span class="number">18</span>);</span><br><span class="line">getName.<span class="title class_">MyApply</span>(ob, [<span class="number">18</span>]);</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> bindGetName = getName.<span class="title class_">MyBind</span>(ob);</span><br><span class="line"><span class="title function_">bindGetName</span>(<span class="number">19</span>);</span><br><span class="line"><span class="title function_">bindGetName</span>(<span class="number">20</span>);</span><br></pre></td></tr></table></figure>



<h3 id="JavaScript-函数增强"><a href="#JavaScript-函数增强" class="headerlink" title="JavaScript 函数增强"></a>JavaScript 函数增强</h3><h4 id="函数对象的属性"><a href="#函数对象的属性" class="headerlink" title="函数对象的属性"></a>函数对象的属性</h4><blockquote>
<p>  传统行数创建就存在的属性 </p>
</blockquote>
<p>name<br>length（定义时明确形参的个数，不包括剩余参数 ）<br>argument （类数组对象，类数组转数组的多种方式 ，箭头函数自己无 argument ）</p>
<blockquote>
<p>  剩余参数</p>
</blockquote>
<p>形参中将不确定的参数放进一个数组中 </p>
<p><strong>rest</strong> 剩余参数与<strong>argument</strong>不同的是，它是一个<strong>真正的数组</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">arg</span>(<span class="params">a,b,...argsxxx</span>)&#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(argsxxx) <span class="comment">// [3,4,5]</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="title function_">arg</span>(<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>)</span><br></pre></td></tr></table></figure>

<h4 id="纯函数"><a href="#纯函数" class="headerlink" title="纯函数"></a>纯函数</h4><ul>
<li>此函数<strong>相同的输入</strong>，必须有<strong>相同的输出</strong>（就是平时用的工具函数）</li>
<li>此函数执行过程中，不能有<strong>副作用</strong><ul>
<li>副作用：执行函数时，除了产生返回值外，还对外面数据产生了附加影响（如修改了全局变量，修改了其他状态等）</li>
</ul>
</li>
</ul>
<h4 id="柯里化-（Currying）"><a href="#柯里化-（Currying）" class="headerlink" title="柯里化 （Currying）"></a>柯里化 （Currying）</h4><blockquote>
<p>  闭包的一种使用场景，</p>
</blockquote>
<p> 只传递<strong>一部分参数</strong>来调用某个函数，让它返回一个函数去处理剩余参数，这个<strong>过程就叫柯里化</strong></p>
<p>柯里化<strong>只是对函数的一种转化</strong>，（意义在于前面括号可以提取共有部分，在这个基础上设置其他变化的东西）</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 1.没有柯里化的时候做法</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">logInfo</span>(<span class="params">date, type, message</span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`时间:<span class="subst">$&#123;date&#125;</span> 类型:<span class="subst">$&#123;type&#125;</span> 内容:<span class="subst">$&#123;message&#125;</span>`</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="title function_">logInfo</span>(<span class="string">&quot;2022-06-01&quot;</span>, <span class="string">&quot;DEBUG&quot;</span>, <span class="string">&quot;修复了从服务器请求数据后展示的bug&quot;</span>)</span><br><span class="line"><span class="title function_">logInfo</span>(<span class="string">&quot;2022-06-01&quot;</span>, <span class="string">&quot;DEBUG&quot;</span>, <span class="string">&quot;修复了从服务器请求数据后展示的bug&quot;</span>)</span><br><span class="line"><span class="title function_">logInfo</span>(<span class="string">&quot;2022-06-01&quot;</span>, <span class="string">&quot;FEATURE&quot;</span>, <span class="string">&quot;新建过滤功能&quot;</span>)</span><br><span class="line"><span class="title function_">logInfo</span>(<span class="string">&quot;2022-06-01&quot;</span>, <span class="string">&quot;FEATURE&quot;</span>, <span class="string">&quot;新建过滤功能 &quot;</span>)</span><br><span class="line">        </span><br><span class="line"><span class="comment">// 2.对函数进行柯里化: 柯里化函数的做法 =========================================</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">logInfo</span>(<span class="params">date</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">function</span> (<span class="params">type</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">function</span> (<span class="params">message</span>) &#123;</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(</span><br><span class="line">                <span class="string">`时间:<span class="subst">$&#123;date&#125;</span> 类型:<span class="subst">$&#123;type&#125;</span> 内容:<span class="subst">$&#123;message&#125;</span>`</span></span><br><span class="line">            );</span><br><span class="line">        &#125;;</span><br><span class="line">    &#125;;</span><br><span class="line">&#125;</span><br><span class="line"><span class="title function_">logInfo</span>(<span class="string">&quot;2022-06-01&quot;</span>)(<span class="string">&quot;DEFAULT&quot;</span>)(<span class="string">&quot;这时一个默认日志&quot;</span>);</span><br><span class="line"><span class="keyword">var</span> logToday = <span class="title function_">logInfo</span>(<span class="string">&quot;2022-06-01&quot;</span>); <span class="comment">// 固定第个参数</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 打印debug日志</span></span><br><span class="line"><span class="keyword">var</span> logTodayDebug = <span class="title function_">logToday</span>(<span class="string">&quot;DEBUG&quot;</span>); <span class="comment">// 设置类型为 DEBUG</span></span><br><span class="line"><span class="title function_">logTodayDebug</span>(<span class="string">&quot;修复界面搜索按钮点击的bug&quot;</span>);</span><br><span class="line"><span class="title function_">logTodayDebug</span>(<span class="string">&quot;修复界面搜索按钮点击的bug&quot;</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> logTodayFeature = <span class="title function_">logToday</span>(<span class="string">&quot;FEATURE&quot;</span>); <span class="comment">// 设置类型为 FEATURE</span></span><br><span class="line"><span class="title function_">logTodayFeature</span>(<span class="string">&quot;新建过滤功能&quot;</span>);</span><br><span class="line"><span class="title function_">logTodayFeature</span>(<span class="string">&quot;新建搜索功能&quot;</span>);</span><br></pre></td></tr></table></figure>

<h4 id="额外知识（少用）"><a href="#额外知识（少用）" class="headerlink" title="额外知识（少用）"></a>额外知识（少用）</h4><h5 id="with"><a href="#with" class="headerlink" title="with"></a>with</h5><blockquote>
<p>  强行插入作用域，不推荐使用</p>
</blockquote>
 <figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = &#123;</span><br><span class="line">    <span class="attr">message</span>: <span class="string">&quot;Hello World&quot;</span>,</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">with</span> (obj) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(message);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="eval"><a href="#eval" class="headerlink" title="eval"></a>eval</h5><blockquote>
<p>  允许执行代码字符串，将传入的函数当做js代码运行，并将最后一句执行语句结果作为返回值</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> codeString = <span class="string">`var name = &quot;why&quot;; console.log(name); console.log(message); &quot;abc&quot;;`</span>;</span><br><span class="line"><span class="keyword">var</span> result = <span class="built_in">eval</span>(codeString);</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(result);</span><br></pre></td></tr></table></figure>

<h5 id="严格模式"><a href="#严格模式" class="headerlink" title="严格模式"></a>严格模式</h5><p>JS 早期设计存在一些缺陷，浏览器更加<strong>严格的检测代码</strong>，通过<strong>抛出错误</strong>消除原因的<strong>静默错误</strong></p>
<ul>
<li>无法意外创建全局变量</li>
<li>不允许使用 with</li>
<li>不允许视图删除不可删除的对象属性</li>
<li>在严格模式下, this不绑定全局对象而是undefined</li>
<li>……</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 给整个script开启严格模式</span></span><br><span class="line"><span class="meta">&quot;use strict&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 给一个函数开启严格模式</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">foo</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="string">&quot;use strict&quot;</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 默认就是严格模式</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Person</span> &#123;&#125;</span><br></pre></td></tr></table></figure>



<h3 id="JavaScript-对象增强"><a href="#JavaScript-对象增强" class="headerlink" title="JavaScript 对象增强"></a>JavaScript 对象增强</h3><h4 id="数据属性描述符"><a href="#数据属性描述符" class="headerlink" title="数据属性描述符"></a>数据属性描述符</h4><p>限制一个属性能做什么不能做什么</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = &#123;</span><br><span class="line">    <span class="attr">name</span>: <span class="string">&quot;why&quot;</span>, <span class="comment">// configurable: true</span></span><br><span class="line">    <span class="attr">age</span>: <span class="number">18</span>,</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 给 obj 对象的 name 属性添加 数据描述符 </span></span><br><span class="line"><span class="title class_">Object</span>.<span class="title function_">defineProperty</span>(obj, <span class="string">&quot;name&quot;</span>, &#123;</span><br><span class="line">    <span class="attr">configurable</span>: <span class="literal">false</span>, <span class="comment">// 告诉js引擎, obj对象的name属性不可以被删除</span></span><br><span class="line">    <span class="attr">enumerable</span>: <span class="literal">false</span>, <span class="comment">// 告诉js引擎, obj对象的name属性不可枚举(for in/Object.keys ,遍历的时候不显示)</span></span><br><span class="line">    <span class="attr">writable</span>: <span class="literal">false</span>, <span class="comment">// 告诉js引擎, obj对象的name属性不写入(只读属性 readonly)</span></span><br><span class="line">    <span class="attr">value</span>: <span class="string">&quot;coderwhy&quot;</span>, <span class="comment">// 告诉js引擎, 返回这个value</span></span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 通过Object.defineProperty方式添加的属性，configurable 默认 true</span></span><br><span class="line"><span class="title class_">Object</span>.<span class="title function_">defineProperty</span>(obj, <span class="string">&quot;address&quot;</span>, &#123;&#125;);</span><br></pre></td></tr></table></figure>

<h4 id="存取属性描述符"><a href="#存取属性描述符" class="headerlink" title="存取属性描述符"></a>存取属性描述符</h4><p>存取属性描述符，通过<strong>两个函数</strong>精准控制<strong>存的过程</strong>和<strong>取的过程</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> *  vue2响应式原理 （响应式就是监听到变化，更新视图）</span></span><br><span class="line"><span class="comment"> *  通过 oninput 事件监听数据变化</span></span><br><span class="line"><span class="comment"> *  当数据发生变化，触发属性的 set，在 set 中将视图中的 &#123;&#123;xxx&#125;&#125; 替换为 最新值</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">var</span> obj = &#123;</span><br><span class="line">    <span class="attr">name</span>: <span class="string">&quot;why&quot;</span>,</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 对obj对象中的name添加描述符(存取属性描述符)</span></span><br><span class="line"><span class="keyword">var</span> _name = <span class="string">&quot;&quot;</span>;</span><br><span class="line"><span class="title class_">Object</span>.<span class="title function_">defineProperty</span>(obj, <span class="string">&quot;name&quot;</span>, &#123;</span><br><span class="line">    <span class="attr">configurable</span>: <span class="literal">true</span>,</span><br><span class="line">    <span class="attr">enumerable</span>: <span class="literal">false</span>,</span><br><span class="line">    <span class="attr">set</span>: <span class="keyword">function</span> (<span class="params">value</span>) &#123;  <span class="comment">// 当属性name被赋值了，我们可以做一些事情</span></span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;set方法被调用了&quot;</span>, value);</span><br><span class="line">        _name = value;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="attr">get</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123; <span class="comment">// 当属性name被查询了，我们可以做一些事情</span></span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;get方法被调用了&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> _name;</span><br><span class="line">    &#125;,</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<h4 id="对象中的写法"><a href="#对象中的写法" class="headerlink" title="对象中的写法"></a>对象中的写法</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = &#123;</span><br><span class="line">    <span class="attr">_name</span>: <span class="string">&quot;why&quot;</span>,</span><br><span class="line">    <span class="comment">// setter方法</span></span><br><span class="line">    <span class="keyword">set</span> <span class="title function_">name</span>(<span class="params">value</span>) &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">_name</span> = value;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="comment">// getter方法</span></span><br><span class="line">    <span class="keyword">get</span> <span class="title function_">name</span>() &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">_name</span>;</span><br><span class="line">    &#125;,</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">obj.<span class="property">name</span> = <span class="string">&quot;kobe&quot;</span>;</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(obj.<span class="property">name</span>); </span><br></pre></td></tr></table></figure>



<h3 id="面向对象"><a href="#面向对象" class="headerlink" title="面向对象"></a>面向对象</h3><p><code>函数.prototype 显示原型</code> —–<code>对象.__proto__ 隐式原型</code> —–<code>对象.__proto__.__proto__ 原型链</code></p>
<h4 id="原型"><a href="#原型" class="headerlink" title="原型"></a>原型</h4><blockquote>
<p>  每一个对象都有原型 [[Prototype]]</p>
</blockquote>
<p>对象原型</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = &#123;</span><br><span class="line">    <span class="attr">name</span>: <span class="string">&quot;why&quot;</span>,</span><br><span class="line">    <span class="attr">age</span>: <span class="number">18</span>,</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 查看对象的原型</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(obj.<span class="property">__proto__</span>); <span class="comment">// 浏览器实现的，非标准</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="title class_">Object</span>.<span class="title function_">getPrototypeOf</span>(obj)); </span><br></pre></td></tr></table></figure>

<p>函数原型</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">Foo</span>(<span class="params">name</span>)&#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">name</span> = name;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 将函数看做普通对象,有__proto__ 属性</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="title class_">Foo</span>.<span class="property">__proto__</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 原型自带属性 </span></span><br><span class="line"><span class="variable constant_">FOO</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">constructor</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 将函数当做函数使用，new的时候，将prototype 赋值给实例对象的 __proto__，设置方法 </span></span><br><span class="line"><span class="variable constant_">FOO</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="title function_">getName</span>(<span class="params"></span>)&#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>.<span class="property">name</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 属性保存在构造函数体，每new个实例都会执行构造函数，有自己的单独属性</span></span><br><span class="line"><span class="comment">// 方法存在 prototype 原型中，每个实例共有</span></span><br><span class="line"><span class="keyword">let</span> fo = <span class="keyword">new</span> <span class="title class_">Foo</span>(<span class="string">&#x27;name&#x27;</span>)</span><br><span class="line">fo.<span class="title function_">getName</span>(); <span class="comment">// 这时候通过fo实例调用了方法，所以this就是fo实例，this.name 就是fo实例的name</span></span><br></pre></td></tr></table></figure>

<h4 id="原型链"><a href="#原型链" class="headerlink" title="原型链"></a>原型链</h4><p>一个对象查找一个属性或方法，自己身上找不到，就去__proto__中找，__proto__找不到，就去__proto__对象的__proto__中找，形成的路径就是<strong>原型链</strong></p>
<p><img src= "" data-lazy-src="/../..%5Cstatic%5Cimg%5C2023-03-06_170053.jpg"></p>
<h4 id="new-实现原理"><a href="#new-实现原理" class="headerlink" title="new 实现原理"></a>new 实现原理</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// myNew</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">Dog</span>(<span class="params">name, age</span>) &#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">name</span> = name;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">age</span> = age;</span><br><span class="line">&#125;</span><br><span class="line"><span class="title class_">Dog</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">getName</span> = <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>.<span class="property">name</span>);</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">myNew</span>(<span class="params">Fun, ...args</span>) &#123;</span><br><span class="line">    <span class="keyword">let</span> obj = &#123;&#125;; <span class="comment">// 未来的实例对象</span></span><br><span class="line">    obj.<span class="property">__proto__</span> = <span class="title class_">Fun</span>.<span class="property"><span class="keyword">prototype</span></span>; <span class="comment">// 使实例对象原型链 指向构造函数的 prototype</span></span><br><span class="line">    <span class="keyword">let</span> res = <span class="title class_">Fun</span>.<span class="title function_">apply</span>(obj, args); <span class="comment">// 调用一次构造函数，将this指向实例对象，时属性加到 obj 中</span></span><br><span class="line">    <span class="keyword">return</span> res <span class="keyword">instanceof</span> <span class="title class_">Object</span> ? res : obj; <span class="comment">// 所有构造函数不能返回对象，可以返回基本类型数据，但无效</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> dog = <span class="title function_">myNew</span>(<span class="title class_">Dog</span>, <span class="string">&quot;dog1&quot;</span>, <span class="number">1</span>);</span><br><span class="line"><span class="keyword">let</span> dog2 = <span class="title function_">myNew</span>(<span class="title class_">Dog</span>, <span class="string">&quot;dog2&quot;</span>, <span class="number">1</span>);</span><br><span class="line">dog.<span class="title function_">getName</span>(); <span class="comment">// this 就是 dog, new dog 时新创建的 obj</span></span><br><span class="line">dog2.<span class="title function_">getName</span>(); <span class="comment">// this 就是 dog2，new dog2 时新创建的 obj</span></span><br><span class="line"></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="title class_">Fun</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">constructor</span>); <span class="comment">// 这个属性默认指向构造函数，所有实例可以通过__proto__拿到这个属性</span></span><br></pre></td></tr></table></figure>

<h4 id="对象方法补充"><a href="#对象方法补充" class="headerlink" title="对象方法补充"></a>对象方法补充</h4><ul>
<li><strong>hasOwnProperty：</strong>判断对象自生是否存在某个属性，不包含原型，原型链</li>
<li><code>&#39;name&#39; in info</code>：判断<code>name</code>属性是否在 <code>info</code>对象上，或者在<code>info</code>对象的原型链上</li>
<li><code>for(var key in info)&#123;&#125;</code>：<code>for in</code>变量的不只是对象自身的属性，还有原型上的属性（不查找不可枚举的属性）</li>
<li><code>实例 instanceof FOO </code>：判断某个实例是否是<strong>FOO构造函数</strong>的实例（去实例的原型链查找是否有 <strong>constructor 为 FOO</strong> 的原型）<ul>
<li>实例原型链上所有 constructor 指向的类 都会为 true</li>
</ul>
</li>
<li><strong>isPrototypeOf：</strong></li>
<li>Object.setPrototypeOf(obj, Con.prototype);</li>
</ul>
<h4 id="面向对象三大特性"><a href="#面向对象三大特性" class="headerlink" title="面向对象三大特性"></a>面向对象三大特性</h4><h5 id="封装"><a href="#封装" class="headerlink" title="封装"></a>封装</h5><ul>
<li>将属性方法，封装到一个类中，也是封装的过程</li>
</ul>
<h5 id="继承"><a href="#继承" class="headerlink" title="继承"></a>继承</h5><ul>
<li>将重复的代码逻辑抽取到父类中</li>
<li>js 的继承就是基于原型链，把某个类的 prototype，的__proto__ 指向 哪个类的prototype，就是继承了那个类</li>
<li>Object 构造函数，是所有类的父类</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 父级</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">Parent</span>(<span class="params">name</span>) &#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">name</span> = name;</span><br><span class="line">&#125;</span><br><span class="line"><span class="title class_">Parent</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">msg</span> = <span class="string">&quot;父级 msg&quot;</span>; </span><br><span class="line"><span class="title class_">Parent</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">go1</span> = <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;go1&quot;</span>);</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 子集</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">Subset</span>(<span class="params">name</span>) &#123;</span><br><span class="line">    <span class="title class_">Parent</span>.<span class="title function_">call</span>(<span class="variable language_">this</span>, name); <span class="comment">// 属性继承</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 如果不想直接用 __proto__，执行需要继承那个类的实例，这个实例，自然能通过__proto__指向 Parent.prototype</span></span><br><span class="line"><span class="comment">// Subset.prototype = new Parent(&quot;父级name&quot;);</span></span><br><span class="line"><span class="comment">// Subset.prototype.__proto__ = Parent.prototype; // 方法继承</span></span><br><span class="line"><span class="title class_">Object</span>.<span class="title function_">setPrototypeOf</span>(<span class="title class_">Subset</span>.<span class="property"><span class="keyword">prototype</span></span>, <span class="title class_">Parent</span>.<span class="property"><span class="keyword">prototype</span></span>); <span class="comment">// Object.setPrototypeOf 兼容性更好一点</span></span><br><span class="line"></span><br><span class="line"><span class="title class_">Subset</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">go2</span> = <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;go2&quot;</span>);</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> sub = <span class="keyword">new</span> <span class="title class_">Subset</span>(<span class="string">&quot;sub1&quot;</span>);</span><br><span class="line">sub.<span class="title function_">go2</span>();</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(sub.<span class="property">name</span>);</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(sub.<span class="property">msg</span>);</span><br></pre></td></tr></table></figure>

<h5 id="多态"><a href="#多态" class="headerlink" title="多态"></a>多态</h5><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 其他语言严格的说法</span></span><br><span class="line"><span class="comment">// 1.必须有继承(实现接口)</span></span><br><span class="line"><span class="comment">// 2.必须有父类引用指向子类对象</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 为不同数据类型，提供统一的接口</span></span><br><span class="line"><span class="comment">// 使用单一的符号来表示不同的类型</span></span><br></pre></td></tr></table></figure>



<h3 id="ES6-的-Class"><a href="#ES6-的-Class" class="headerlink" title="ES6 的 Class"></a>ES6 的 Class</h3><h4 id="对比构造函数"><a href="#对比构造函数" class="headerlink" title="对比构造函数"></a>对比构造函数</h4><blockquote>
<p>  相对于ES5 的写法<strong>内聚性</strong>更强 (<strong>高内聚</strong>就是说属于一个整体的东西尽量放在一起)</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// ES6 的 Class 就是 ES5构造函数的语法糖，是可以相互转换的</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// function定义类</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">Person1</span>(<span class="params">name, age</span>) &#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">name</span> = name;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">age</span> = age; </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 创建一个类方法</span></span><br><span class="line"><span class="title class_">Parent</span>.<span class="property">staticFunction</span> = <span class="title function_">staticFunction</span>(<span class="params"></span>)&#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;类方法，静态方法&#x27;</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="title class_">Person1</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">running</span> = <span class="keyword">function</span> (<span class="params"></span>) &#123;&#125;;</span><br><span class="line"><span class="title class_">Person1</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">eating</span> = <span class="keyword">function</span> (<span class="params"></span>) &#123;&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> p1 = <span class="keyword">new</span> <span class="title class_">Person1</span>(<span class="string">&quot;why&quot;</span>, <span class="number">18</span>);</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(p1.<span class="property">__proto__</span> === <span class="title class_">Person1</span>.<span class="property"><span class="keyword">prototype</span></span>);</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="title class_">Person1</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">constructor</span>);</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="keyword">typeof</span> <span class="title class_">Person1</span>); <span class="comment">// function</span></span><br><span class="line"><span class="title class_">Person1</span>.<span class="title function_">staticFunction</span>() <span class="comment">// 调用静态方法</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 不同点: 作为普通函数去调用</span></span><br><span class="line"><span class="title class_">Person1</span>(<span class="string">&quot;abc&quot;</span>, <span class="number">100</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">//==========================================================================</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// class定义类</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Person2</span> &#123;</span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params">name, age</span>) &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">name</span> = name;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">age</span> = age;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">static</span> <span class="title function_">staticFunction</span>(<span class="params"></span>)&#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;类方法，静态方法&#x27;</span>)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="title function_">running</span>(<span class="params"></span>) &#123;&#125;</span><br><span class="line">    <span class="title function_">eating</span>(<span class="params"></span>) &#123;&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> p2 = <span class="keyword">new</span> <span class="title class_">Person2</span>(<span class="string">&quot;kobe&quot;</span>, <span class="number">30</span>);</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(p2.<span class="property">__proto__</span> === <span class="title class_">Person2</span>.<span class="property"><span class="keyword">prototype</span></span>);</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="title class_">Person2</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">constructor</span>);</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="keyword">typeof</span> <span class="title class_">Person2</span>);</span><br><span class="line"><span class="title class_">Person2</span>.<span class="title function_">staticFunction</span>() <span class="comment">// 调用静态方法</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 不同点: class定义的类, 不能作为一个普通的函数进行调用</span></span><br><span class="line"><span class="title class_">Person2</span>(<span class="string">&quot;cba&quot;</span>, <span class="number">0</span>);</span><br></pre></td></tr></table></figure>

<h4 id="类的描述符"><a href="#类的描述符" class="headerlink" title="类的描述符"></a>类的描述符</h4><blockquote>
<p>  程序员<strong>约定俗成</strong>的规范，不让外部访问的属性就以下划线开头，ES13后<strong>语言层面新增</strong> #开头为私有属性</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 访问器的应用场景</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Rectangle</span> &#123;</span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params">x, y, width, height</span>) &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">x</span> = x;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">y</span> = y;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">width</span> = width;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">height</span> = height;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">get</span> <span class="title function_">position</span>() &#123;</span><br><span class="line">        <span class="keyword">return</span> &#123; <span class="attr">x</span>: <span class="variable language_">this</span>.<span class="property">x</span>, <span class="attr">y</span>: <span class="variable language_">this</span>.<span class="property">y</span> &#125;;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">get</span> <span class="title function_">size</span>() &#123;</span><br><span class="line">        <span class="keyword">return</span> &#123; <span class="attr">width</span>: <span class="variable language_">this</span>.<span class="property">width</span>, <span class="attr">height</span>: <span class="variable language_">this</span>.<span class="property">height</span> &#125;;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> rect1 = <span class="keyword">new</span> <span class="title class_">Rectangle</span>(<span class="number">10</span>, <span class="number">20</span>, <span class="number">100</span>, <span class="number">200</span>);</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(rect1.<span class="property">position</span>);</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(rect1.<span class="property">size</span>);</span><br></pre></td></tr></table></figure>

<h4 id="ES6-的继承"><a href="#ES6-的继承" class="headerlink" title="ES6 的继承"></a>ES6 的继承</h4><blockquote>
<p>  super 可以在子类的构造函数、静态方法、原型方法中调用 </p>
</blockquote>
<blockquote>
<p>  js 只支持单继承</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 定义父类</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Person</span> &#123;</span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params">name</span>) &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">name</span> = name;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="title function_">running</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;running~&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Student</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Person</span> &#123;</span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params">name, age</span>) &#123;</span><br><span class="line">        <span class="variable language_">super</span>(name); <span class="comment">//必须先调用super</span></span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">age</span> = age;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="title function_">running</span>(<span class="params"></span>) &#123; <span class="comment">// 重写父类方法</span></span><br><span class="line">        <span class="variable language_">super</span>.<span class="title function_">running</span>() <span class="comment">// 调用父类的方法, 在父类基础上写上自己的东西</span></span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;Student running~&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="title function_">studying</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;studying~&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> stu = <span class="keyword">new</span> <span class="title class_">Student</span>(<span class="string">&quot;why&quot;</span>, <span class="number">18</span>);</span><br><span class="line">stu.<span class="title function_">running</span>();</span><br></pre></td></tr></table></figure>

<blockquote>
<p>  继承内置方法，<code>MyArray</code> 扩展一些个人性，Array没有的东西</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">MyArray</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Array</span> &#123;</span><br><span class="line">    xxx</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="title class_">Array</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">xxx</span> = <span class="keyword">function</span>(<span class="params"></span>)&#123;&#125;</span><br></pre></td></tr></table></figure>

<h3 id="ES6-增强"><a href="#ES6-增强" class="headerlink" title="ES6 增强"></a>ES6 增强</h3><h4 id="对象字面量"><a href="#对象字面量" class="headerlink" title="对象字面量"></a>对象字面量</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> name = <span class="string">&#x27; &#x27;</span>; </span><br><span class="line"><span class="keyword">var</span> key = <span class="string">&quot;address&quot;</span> + <span class="string">&quot; city&quot;</span>;</span><br><span class="line"><span class="keyword">var</span> obj = &#123;</span><br><span class="line">    name, <span class="comment">// 1、属性</span></span><br><span class="line">    <span class="title function_">foo</span>(<span class="params"></span>)&#123;&#125;, <span class="comment">// 2、方法</span></span><br><span class="line">    [key]:<span class="string">&#x27;xx&#x27;</span> <span class="comment">//3、自定义变量名</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="解构"><a href="#解构" class="headerlink" title="解构"></a>解构</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 数组结构</span></span><br><span class="line"><span class="keyword">let</span> [a,b] = [<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>]</span><br><span class="line"><span class="keyword">let</span> [c,,f] = [<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>]</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(a,b) <span class="comment">// 1,2</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(c,f) <span class="comment">// 4,6</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 对象的结构</span></span><br><span class="line"><span class="keyword">let</span> &#123;<span class="attr">name</span>: myname, age,...other&#125; = &#123;<span class="attr">name</span>:<span class="string">&quot;lzo&quot;</span>,<span class="attr">age</span>:<span class="number">18</span>,<span class="attr">height</span>:<span class="number">190</span>,<span class="attr">money</span>:<span class="string">&#x27;more&#x27;</span>&#125;</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(myname) <span class="comment">// lzo</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(age) <span class="comment">// 18</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(other) <span class="comment">// &#123;height:190,money:&#x27;more&#x27;&#125;</span></span><br></pre></td></tr></table></figure>

<h4 id="新的ECMA代码执行描述"><a href="#新的ECMA代码执行描述" class="headerlink" title="新的ECMA代码执行描述"></a>新的ECMA代码执行描述</h4><p><a target="_blank" rel="noopener" href="https://www.ecma-international.org/publications-and-standards/standards/ecma-262/">ecma-262</a>  找到 Executable Code and Execution Contexts</p>
<p>ES6 之前的代码描述</p>
<ul>
<li><p><strong>执行上下文栈：</strong><code>（Execution Context Stack）</code>用于执行上下文的<strong>栈结构</strong></p>
</li>
<li><p><strong>执行上下文：</strong><code>（Execution Context）</code>代码在执行前<strong>会先创建</strong>的执行上下文（<code>GEC、FEC</code>）</p>
<ul>
<li>关联 VO对象 、作用域链、this</li>
</ul>
</li>
<li><p><strong>变量对象：</strong><code>（Variable Object）</code>上下文管理的<strong>VO对象</strong>，用于<strong>记录函数</strong>和<strong>变量</strong>的声明</p>
</li>
<li><p><strong>全局对象：</strong><code>（Global Object）</code> <strong>GO</strong>是全局<strong>执行上下文</strong>关联的<strong>VO对象</strong></p>
</li>
<li><p><strong>激活对象：</strong><code>(Activation Object)</code> <strong>AO</strong>函数<strong>执行上下文</strong>管理的<strong>VO对象</strong></p>
</li>
<li><p><strong>作用域链：</strong><code>（scope chain）</code>用于关联指向上下文栈的变量查找</p>
</li>
</ul>
<p>ES6 的代码描述</p>
<ul>
<li><p><strong>执行上下文栈：</strong><code>（Execution Context Stack）</code>用于执行上下文的<strong>栈结构</strong></p>
</li>
<li><p><strong>执行上下文：</strong><code>（Execution Context）</code>代码在执行前<strong>会先创建</strong>的执行上下文（<code>GEC、FEC</code>）</p>
<ul>
<li>关联第一个词法环境 <code>Lexical Environments</code> 处理 let&#x2F;const 变量</li>
<li>关联第二个变量 环境 <code>Variable Environments</code>  处理 var 变量 ，会产生变量提升</li>
<li>它们初始化时时同一个值</li>
</ul>
</li>
<li><p><strong>词法环境：</strong><code>(Lexical Environments)</code> <strong>环境记录</strong> 和 <strong>外部词法环境</strong>组成</p>
<ul>
<li>函数声明、代码块语句、try-catch语句 被执行是都会创建<strong>局部词法环境</strong>（<strong>并不是EC</strong>,而是<strong>EC</strong>中<strong>变量或函数</strong>的集合）</li>
<li>环境记录：<code>Environment Record</code>    <ul>
<li>全局上下文 LE 的环境记录，与以前的 GO 类似，但不是window（定义全局的变量和函数标识符）<ul>
<li>全局较特殊，包含 Window  <strong>用于储存var变量</strong>、和 声明式环境记录 <strong>用于储存let&#x2F;cost</strong></li>
</ul>
</li>
<li>局部上下文 LE 的环境记录，与以前的 AO 类似 （定义局部的变量和函数标识符）</li>
<li>LE 创建就会<strong>直接记录 let&#x2F;count 的变量</strong>，但是要等到<strong>赋值才能访问</strong>，称为<strong>暂时性死区</strong></li>
</ul>
</li>
<li>外部词法环境：<code>Outer LE</code>  全局词法环境这个为null</li>
</ul>
</li>
</ul>
<h4 id="let-const"><a href="#let-const" class="headerlink" title="let&#x2F;const"></a>let&#x2F;const</h4><ul>
<li><p>不允许变量的<strong>重复</strong>声明</p>
</li>
<li><p>没有变量提升，<strong>词法环境创建时</strong>let&#x2F;const变量也<strong>直接创建</strong>，没赋值前有<strong>暂时性死区</strong>，无法访问</p>
<ul>
<li>暂时性死区，变量被创建 到 被赋值之间的<strong>区域</strong>，与定义位置无关</li>
</ul>
</li>
<li><p>全局var变量添加到<strong>window</strong>，let&#x2F;const 的变量<strong>不会添加到window</strong>，而是另外一个对象，谷歌表现为Script</p>
</li>
<li><p>let&#x2F;const&#x2F;function&#x2F;class所在的 {} 中，对相关变量，会形成<strong>块级作用域</strong>，与执行上下文无关</p>
<ul>
<li><pre><code class="javascript">foo(); // foo is not defined
&#123;
    let a = 1;
    function foo() &#123;
        console.log(&quot;111&quot;);
    &#125;
&#125;
foo(); // 不报错
console.log(a); // a is not defined

// 外面无法访问a，函数做了特殊处理，可以在块级作用域后面后面使用
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">####  模板字符串</span><br><span class="line"></span><br><span class="line">```javascript</span><br><span class="line">// 基本使用</span><br><span class="line">let s  = &#x27;123456&#x27;</span><br><span class="line">let str = `this is a template $&#123;s&#125;`</span><br><span class="line"></span><br><span class="line">// 标签模板字符串，react的 css in js 就是这么调用的</span><br><span class="line">function foo(...args) &#123;</span><br><span class="line">    console.log(&quot;参数:&quot;, args);</span><br><span class="line">&#125;</span><br><span class="line">foo`my name is $&#123;name&#125;, age is $&#123;age&#125;, height is $&#123;1.88&#125;`; // 调用</span><br><span class="line"></span><br><span class="line">// 其他字符串操作</span><br><span class="line">let str = &quot;123abc456&quot;;</span><br><span class="line">console.log(str.includes(&quot;abc&quot;)); // true</span><br><span class="line">console.log(str.startsWith(&quot;123&quot;)); // true</span><br><span class="line">console.log(str.endsWith(&quot;456&quot;)); // true</span><br></pre></td></tr></table></figure>
</code></pre>
</li>
</ul>
</li>
</ul>
<h3 id="对象"><a href="#对象" class="headerlink" title="对象"></a>对象</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> info = <span class="title class_">Object</span>.<span class="title function_">create</span>(<span class="literal">null</span>) <span class="comment">// 创建info对象，并且让对象的原型指向null</span></span><br></pre></td></tr></table></figure>



<h4 id="ES6函数增强"><a href="#ES6函数增强" class="headerlink" title="ES6函数增强"></a>ES6函数增强</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 默认参数</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">foo</span>(<span class="params">a=<span class="number">1</span></span>)&#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 箭头函数，没有 prototype 但是有 __proto__ </span></span><br><span class="line"><span class="comment">// 不绑定this、argument、super</span></span><br></pre></td></tr></table></figure>

<h4 id="展开"><a href="#展开" class="headerlink" title="展开"></a>展开</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 一开始只能展开数组和字符串</span></span><br><span class="line"><span class="keyword">let</span> array = [<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>]</span><br><span class="line"><span class="keyword">let</span> newArray = [...array,<span class="number">4</span>,<span class="number">5</span>] <span class="comment">// 1,2,3,4,5</span></span><br><span class="line"><span class="keyword">let</span> str = [...<span class="string">&quot;abc&quot;</span>] <span class="comment">// a,b,c</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// ES9（ES2018）可以在构建字面量对象时，展开对象</span></span><br><span class="line"><span class="keyword">let</span> obj = &#123;</span><br><span class="line">    <span class="attr">a</span>:<span class="number">1</span>,</span><br><span class="line">    <span class="attr">b</span>:<span class="number">2</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> info = &#123;</span><br><span class="line">    ...obj,</span><br><span class="line">    <span class="attr">c</span>:<span class="number">3</span></span><br><span class="line">&#125; <span class="comment">// &#123;a: 1, b: 2, c: 3&#125;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 合并两个对象，并且替换属性c</span></span><br><span class="line"><span class="keyword">let</span> newInfo = &#123;...obj,...info, <span class="attr">c</span>:<span class="number">4</span>&#125;</span><br></pre></td></tr></table></figure>

<h4 id="数值表示"><a href="#数值表示" class="headerlink" title="数值表示"></a>数值表示</h4><blockquote>
<p>  规范类进制写法</p>
</blockquote>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">规定 0b、0o、0x 开头代表二进制、八进制、十进制（以前0开头当做八进制）</span>  </span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">新出的 过大的数字可以用下划线连接，任意位置 10_000_00_0</span></span><br></pre></td></tr></table></figure>

<h4 id="Symbol"><a href="#Symbol" class="headerlink" title="Symbol"></a>Symbol</h4><blockquote>
<p>  ES6 新增的基本数据类型</p>
</blockquote>
<ul>
<li><p>Symbol 函数可以生成一个独一无二的值</p>
</li>
<li><p>在别人传给你的对象添加新属性时，防止对象属性冲突</p>
</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 生成唯一的值</span></span><br><span class="line"><span class="keyword">const</span> sym = <span class="title class_">Symbol</span>();</span><br><span class="line"><span class="keyword">const</span> bol = <span class="title class_">Symbol</span>();</span><br><span class="line">obj[sym] = <span class="string">&#x27;xxx&#x27;</span></span><br><span class="line">obj[bol] = <span class="string">&#x27;yyy&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 非要生成相同的 Symbol，通过 Symbol.for 传入相同的描述</span></span><br><span class="line"><span class="keyword">const</span> s5 = <span class="title class_">Symbol</span>.<span class="title function_">for</span>(<span class="string">&quot;ddd&quot;</span>);</span><br><span class="line"><span class="keyword">const</span> s6 = <span class="title class_">Symbol</span>.<span class="title function_">for</span>(<span class="string">&quot;ddd&quot;</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 获取对象中 Symbol 的 key</span></span><br><span class="line"><span class="title class_">Object</span>.<span class="title function_">getOwnPropertySymbols</span>(obj) </span><br></pre></td></tr></table></figure>

<h4 id="Set-and-Map-数据结构"><a href="#Set-and-Map-数据结构" class="headerlink" title="Set and Map 数据结构"></a>Set and Map 数据结构</h4><h5 id="Set"><a href="#Set" class="headerlink" title="Set"></a>Set</h5><blockquote>
<p>  与数组类似，但是元素不能重复，常用与数组去重</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 1.创建Set</span></span><br><span class="line"><span class="keyword">const</span> set = <span class="keyword">new</span> <span class="title class_">Set</span>();</span><br><span class="line"></span><br><span class="line"><span class="comment">// 2.添加元素</span></span><br><span class="line">set.<span class="title function_">add</span>(<span class="number">10</span>); <span class="comment">// 添加基本元素</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(set);</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> info = &#123;&#125;;</span><br><span class="line"><span class="keyword">const</span> obj = &#123; <span class="attr">name</span>: <span class="string">&quot;obj&quot;</span> &#125;;</span><br><span class="line">set.<span class="title function_">add</span>(info);</span><br><span class="line">set.<span class="title function_">add</span>(obj); <span class="comment">// 添加第二个对象地址</span></span><br><span class="line">set.<span class="title function_">add</span>(obj); <span class="comment">// 无法添加</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(set);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 3.应用场景: 数组的去重,Set 接收一个可迭代对象</span></span><br><span class="line"><span class="keyword">const</span> names = [<span class="string">&quot;abc&quot;</span>, <span class="string">&quot;cba&quot;</span>, <span class="string">&quot;nba&quot;</span>, <span class="string">&quot;cba&quot;</span>, <span class="string">&quot;nba&quot;</span>];</span><br><span class="line"><span class="keyword">const</span> newNames = <span class="title class_">Array</span>.<span class="title function_">from</span>(<span class="keyword">new</span> <span class="title class_">Set</span>(names)); <span class="comment">// [&quot;abc&quot;, &quot;cba&quot;, &quot;nba&quot;];</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 4.Set的其他属性和方法</span></span><br><span class="line"><span class="comment">// 属性</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(set.<span class="property">size</span>);</span><br><span class="line"><span class="comment">// 方法</span></span><br><span class="line"><span class="comment">// 4.1. 添加元素</span></span><br><span class="line">set.<span class="title function_">add</span>(<span class="number">100</span>);</span><br><span class="line"><span class="comment">// 4.2. 删除元素</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(set) <span class="comment">// 下一步才删除，这时打印已经展开是没有obj对象的，这时浏览器做的一些处理</span></span><br><span class="line">set.<span class="title function_">delete</span>(obj);</span><br><span class="line"><span class="comment">// 4.3. 判断是否存在</span></span><br><span class="line">set.<span class="title function_">has</span>(info);</span><br><span class="line"><span class="comment">// 4.4. 清除所有元素</span></span><br><span class="line">set.<span class="title function_">clear</span>()</span><br><span class="line"><span class="comment">// 4.5. forEach</span></span><br><span class="line">set.<span class="title function_">forEach</span>(<span class="function">(<span class="params">item</span>) =&gt;</span> <span class="variable language_">console</span>.<span class="title function_">log</span>(item));</span><br><span class="line"></span><br><span class="line"><span class="comment">// 5.set支持for...of</span></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">const</span> item <span class="keyword">of</span> set) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(item);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h5 id="Map"><a href="#Map" class="headerlink" title="Map"></a>Map</h5><blockquote>
<p>  用于存储映射关系</p>
</blockquote>
<ul>
<li>和对象的差别<ul>
<li>对象不能使用复制类型作为key，**{[info]:’xxx’}** 会被转换成 <strong>[object object]</strong></li>
</ul>
</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 想用对象作为key 时就可以考虑不用对象使用Map</span></span><br><span class="line"><span class="keyword">const</span> map = <span class="keyword">new</span> <span class="title class_">Map</span>();</span><br><span class="line"><span class="comment">// 添加内容</span></span><br><span class="line">map.<span class="title function_">set</span>(info, <span class="string">&quot;aaaa&quot;</span>); </span><br><span class="line"><span class="comment">// 获取内容</span></span><br><span class="line">map.<span class="title function_">get</span>(info))</span><br><span class="line"><span class="comment">// delete方法, 删除内容</span></span><br><span class="line">map.<span class="title function_">delete</span>(info)</span><br><span class="line"><span class="comment">// has方法, 判断内容</span></span><br><span class="line">map.<span class="title function_">has</span>(info)</span><br><span class="line"><span class="comment">// clear方法, 清空内容</span></span><br><span class="line">map.<span class="title function_">clear</span>()</span><br><span class="line"><span class="comment">// forEach方法</span></span><br><span class="line">map.<span class="title function_">forEach</span>(<span class="function"><span class="params">item</span> =&gt;</span> <span class="variable language_">console</span>.<span class="title function_">log</span>(item))</span><br><span class="line"></span><br><span class="line"><span class="comment">// for...of遍历</span></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">const</span> item <span class="keyword">of</span> map) &#123;</span><br><span class="line">    <span class="keyword">const</span> [key, value] = item;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(key, value);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h5 id="WeakSet"><a href="#WeakSet" class="headerlink" title="WeakSet"></a>WeakSet</h5><blockquote>
<p>  Weak 开头都是弱引用，只添加到 WeakSet 的对象，<strong>GC 遇到</strong>还是会把它<strong>当做垃圾回收</strong>，虽然被WeakSet引用着</p>
</blockquote>
<ul>
<li>对比 Set<ul>
<li>WeakSet 只能存放对象类型</li>
<li>不能遍历，很有肯可能遍历的东西，突然被销毁了，很危险</li>
</ul>
</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 应用，限制外部调用类中的方法，当实例被销毁时，由于这边是弱引用，依旧会被GC回收</span></span><br><span class="line"><span class="keyword">const</span> pWeakSet = <span class="keyword">new</span> <span class="title class_">WeakSet</span>();</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Person</span> &#123;</span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params"></span>) &#123;</span><br><span class="line">        pWeakSet.<span class="title function_">add</span>(<span class="variable language_">this</span>); <span class="comment">// 添加每一个实例</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="title function_">running</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (!pWeakSet.<span class="title function_">has</span>(<span class="variable language_">this</span>)) &#123;</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;Type error: 调用的方式不对&quot;</span>);</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;running~&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> p = <span class="keyword">new</span> <span class="title class_">Person</span>();</span><br><span class="line"><span class="comment">// p = null</span></span><br><span class="line">p.<span class="title function_">running</span>();</span><br><span class="line"><span class="keyword">const</span> runFn = p.<span class="property">running</span>;</span><br><span class="line"><span class="title function_">runFn</span>();</span><br><span class="line"><span class="keyword">const</span> obj = &#123; <span class="attr">run</span>: runFn &#125;;</span><br><span class="line">obj.<span class="title function_">run</span>();</span><br></pre></td></tr></table></figure>



<h5 id="WeakMap"><a href="#WeakMap" class="headerlink" title="WeakMap"></a>WeakMap</h5><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">let</span> <span class="variable">obj1</span> <span class="operator">=</span> &#123; name: <span class="string">&quot;why&quot;</span> &#125;;</span><br><span class="line"><span class="type">let</span> <span class="variable">obj2</span> <span class="operator">=</span> &#123; name: <span class="string">&quot;kobe&quot;</span> &#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 1.WeakMap的基本使用</span></span><br><span class="line"><span class="type">const</span> <span class="variable">weakMap</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">WeakMap</span>();</span><br><span class="line"><span class="comment">// weakMap.set(123, &quot;aaa&quot;)</span></span><br><span class="line">weakMap.set(obj1, <span class="string">&quot;aaa&quot;</span>);</span><br><span class="line">weakMap.set(obj2, <span class="string">&quot;bbb&quot;</span>);</span><br><span class="line"></span><br><span class="line">obj1 = <span class="literal">null</span>;</span><br><span class="line">obj2 = <span class="literal">null</span>; <span class="comment">// 因为weakMap是弱引用，这时，遇到GC，会被回收，如果换成Map 应用这obj2,GC就不会回收</span></span><br></pre></td></tr></table></figure>

<h4 id="Proxy-SReflect"><a href="#Proxy-SReflect" class="headerlink" title="Proxy&#x2F;SReflect"></a>Proxy&#x2F;SReflect</h4><h5 id="回顾vue2响应式原理"><a href="#回顾vue2响应式原理" class="headerlink" title="回顾vue2响应式原理"></a>回顾vue2响应式原理</h5><blockquote>
<p>  只能监听简单的get 和 set，后期新增删除的属性无法监听</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> obj = &#123;</span><br><span class="line">    <span class="attr">name</span>: <span class="string">&quot;why&quot;</span>,</span><br><span class="line">    <span class="attr">age</span>: <span class="number">18</span>,</span><br><span class="line">    <span class="attr">height</span>: <span class="number">1.88</span>,</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 对每一个属性使用defineProperty</span></span><br><span class="line"><span class="keyword">const</span> keys = <span class="title class_">Object</span>.<span class="title function_">keys</span>(obj);</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">const</span> key <span class="keyword">of</span> keys) &#123;</span><br><span class="line">    <span class="keyword">let</span> value = obj[key];</span><br><span class="line">    <span class="title class_">Object</span>.<span class="title function_">defineProperty</span>(obj, key, &#123;</span><br><span class="line">        <span class="attr">set</span>: <span class="keyword">function</span> (<span class="params">newValue</span>) &#123;</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`监听: 给<span class="subst">$&#123;key&#125;</span>设置了新的值:`</span>, newValue); <span class="comment">// value改变做一些事情</span></span><br><span class="line">            value = newValue;</span><br><span class="line">        &#125;,</span><br><span class="line">        <span class="attr">get</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`监听: 获取<span class="subst">$&#123;key&#125;</span>的值`</span>);</span><br><span class="line">            <span class="keyword">return</span> value;</span><br><span class="line">        &#125;,</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(obj.<span class="property">age</span>);</span><br><span class="line">obj.<span class="property">age</span> = <span class="number">17</span>;</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(obj.<span class="property">age</span>);</span><br></pre></td></tr></table></figure>

<h5 id="Proxy"><a href="#Proxy" class="headerlink" title="Proxy"></a>Proxy</h5><ul>
<li>希望监听一个对象时，需要先创<strong>建代理对象</strong></li>
<li>之后都是<strong>直接针对代理对象操作</strong></li>
<li>监听整个对象，不针对于某个属性</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> obj = &#123;</span><br><span class="line">    <span class="attr">name</span>: <span class="string">&quot;why&quot;</span>,</span><br><span class="line">    <span class="attr">age</span>: <span class="number">18</span>,</span><br><span class="line">    <span class="attr">height</span>: <span class="number">1.88</span>,</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 1.创建一个Proxy对象</span></span><br><span class="line"><span class="keyword">const</span> objProxy = <span class="keyword">new</span> <span class="title class_">Proxy</span>(obj, &#123;</span><br><span class="line">    <span class="attr">set</span>: <span class="keyword">function</span> (<span class="params">target, key, newValue</span>) &#123; </span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`监听: 监听<span class="subst">$&#123;key&#125;</span>的设置值: `</span>, newValue);</span><br><span class="line">        target[key] = newValue;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="attr">get</span>: <span class="keyword">function</span> (<span class="params">target, key</span>) &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`监听: 监听<span class="subst">$&#123;key&#125;</span>的获取`</span>);</span><br><span class="line">        <span class="keyword">return</span> target[key];</span><br><span class="line">    &#125;,</span><br><span class="line"></span><br><span class="line">    <span class="attr">deleteProperty</span>: <span class="keyword">function</span> (<span class="params">target, key</span>) &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`监听: 监听删除<span class="subst">$&#123;key&#125;</span>属性`</span>);</span><br><span class="line">        <span class="keyword">delete</span> obj.<span class="property">name</span>;</span><br><span class="line">    &#125;,</span><br><span class="line"></span><br><span class="line">    <span class="attr">has</span>: <span class="keyword">function</span> (<span class="params">target, key</span>) &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`监听: 监听in判断 <span class="subst">$&#123;key&#125;</span>属性`</span>);</span><br><span class="line">        <span class="keyword">return</span> key <span class="keyword">in</span>  target;</span><br><span class="line">    &#125;,</span><br><span class="line">   ...</span><br><span class="line">&#125;); </span><br></pre></td></tr></table></figure>

<h5 id="Reflect（反射）"><a href="#Reflect（反射）" class="headerlink" title="Reflect（反射）"></a>Reflect（反射）</h5><blockquote>
<p>  和Math类似，本身就是一个对象，不需要new直接使用</p>
</blockquote>
<ul>
<li>提供很多<strong>操作 JavaScript对象的方法</strong><ul>
<li>Reflect.defineProperty  和 Object.defineProperty</li>
</ul>
</li>
<li>Object本身是一个构造函数，又是JS的顶级类，不适合太多方法</li>
<li>将一些对象本身的一些方法<strong>迁移到 Reflect</strong> 中</li>
<li>Proxy 有的方法， Reflect中也有</li>
</ul>
<blockquote>
<p>  Reflect 一般与 Proxy 共同完成代理</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> obj = &#123;</span><br><span class="line">    <span class="attr">_name</span>: <span class="string">&quot;why&quot;</span>,</span><br><span class="line">    <span class="keyword">set</span> <span class="title function_">name</span>(<span class="params">newValue</span>) &#123; <span class="comment">// 下划线防止递归选好设置</span></span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;this:&quot;</span>, <span class="variable language_">this</span>); <span class="comment">// 默认是obj</span></span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">_name</span> = newValue;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="keyword">get</span> <span class="title function_">name</span>() &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">_name</span>;</span><br><span class="line">    &#125;,</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 1.创建一个Proxy对象</span></span><br><span class="line"><span class="keyword">const</span> objProxy = <span class="keyword">new</span> <span class="title class_">Proxy</span>(obj, &#123;</span><br><span class="line">    <span class="attr">set</span>: <span class="keyword">function</span> (<span class="params">target, key, newValue,receiver</span>) &#123; <span class="comment">// receiver 就是 objProxy</span></span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`监听: 监听<span class="subst">$&#123;key&#125;</span>的设置值: `</span>, newValue);</span><br><span class="line">        <span class="comment">// target[key] = newValue;</span></span><br><span class="line">        </span><br><span class="line">        </span><br><span class="line">        <span class="comment">// 1、代理的目的是不直接操作原对象，通过Reflect 简介操作</span></span><br><span class="line">        <span class="comment">// 2、可以检测操作是否成功</span></span><br><span class="line">        <span class="comment">// 3、receiver，让 target里的getset 的 this 指向 receiver 就是 objProxy</span></span><br><span class="line">        <span class="keyword">let</span> isSuccess = <span class="title class_">Reflect</span>.<span class="title function_">set</span>(target, key, newValue，receiver) </span><br><span class="line">    &#125;,</span><br><span class="line">&#125;); </span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(objProxy.<span class="property">name</span>);</span><br></pre></td></tr></table></figure>



<h4 id="Promise"><a href="#Promise" class="headerlink" title="Promise"></a>Promise</h4><blockquote>
<p>  三种状态</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 1.创建一个Promise对象, 传入一个会立即执行的 executor 回调函数</span></span><br><span class="line"><span class="keyword">const</span> promise = <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">// 1.待定状态 pending</span></span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;111111&quot;</span>);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 注意: Promise的状态一旦被确定下来, 就不会再更改, 也不能再执行某一个回调函数来改变状态</span></span><br><span class="line">    <span class="comment">// 2.兑现状态 fulfilled</span></span><br><span class="line">    <span class="title function_">resolve</span>();</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 3.拒绝状态 rejected</span></span><br><span class="line">    <span class="title function_">reject</span>();</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 第一个.then 返回的是promise，then的回调中如果有返回值，下一个then得到的数据就是返回值,抛出throw异常，就会走catch</span></span><br><span class="line">promise.<span class="title function_">then</span>(<span class="function">(<span class="params">value</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;成功的回调&quot;</span>);</span><br><span class="line">&#125;).<span class="title function_">catch</span>(<span class="function">(<span class="params">err</span>) =&gt;</span> &#123; <span class="comment">// catch也有return，也能得到一个promise，又能.then</span></span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;失败的回调&quot;</span>);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<blockquote>
<p>  传值</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 1.普通值</span></span><br><span class="line"><span class="title function_">resolve</span>([</span><br><span class="line">   &#123;<span class="attr">name</span>: <span class="string">&quot;macbook&quot;</span>, <span class="attr">price</span>: <span class="number">9998</span>, <span class="attr">intro</span>: <span class="string">&quot;有点贵&quot;</span>&#125;,</span><br><span class="line">   &#123;<span class="attr">name</span>: <span class="string">&quot;iPhone&quot;</span>, <span class="attr">price</span>: <span class="number">9.9</span>, <span class="attr">intro</span>: <span class="string">&quot;有点便宜&quot;</span>&#125;,</span><br><span class="line">])</span><br><span class="line"></span><br><span class="line"><span class="comment">// 2.resolve(promise)</span></span><br><span class="line"><span class="comment">// 如果resolve的值本身Promise对象, 那么当前的Promise的状态会有传入的Promise来决定</span></span><br><span class="line"><span class="title function_">resolve</span>(p)</span><br></pre></td></tr></table></figure>

<blockquote>
<p>  then 的两种写法</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">promise.<span class="title function_">then</span>(<span class="function">(<span class="params">value</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;成功的回调&quot;</span>);</span><br><span class="line">&#125;).<span class="title function_">catch</span>(<span class="function">(<span class="params">err</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;失败的回调&quot;</span>);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">promise.<span class="title function_">then</span>(<span class="function">(<span class="params">value</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;成功的回调&quot;</span>);</span><br><span class="line">&#125;,<span class="function">(<span class="params">err</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;失败的回调&quot;</span>);</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<blockquote>
<p>  ES9 finally</p>
</blockquote>
<p>无论是<code>resolve</code>，还是<code>reject</code>，都活走<code>finally</code></p>
<h5 id="类方法"><a href="#类方法" class="headerlink" title="类方法"></a>类方法</h5><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="title class_">Promise</span>.<span class="title function_">resolve</span>(<span class="string">&#x27;hello&#x27;</span>).<span class="title function_">then</span>(<span class="function">(<span class="params">res</span>)=&gt;</span>&#123;&#125;) <span class="comment">// 将数据转换为promise数据</span></span><br><span class="line"><span class="title class_">Promise</span>.<span class="title function_">reject</span>(<span class="string">&#x27;err msg&#x27;</span>).<span class="title function_">catch</span>(<span class="function">(<span class="params">err</span>)=&gt;</span>&#123;&#125;)</span><br><span class="line">promise.<span class="title function_">all</span>([p1,p2,p3]).<span class="title function_">then</span>(<span class="function">(<span class="params">res</span>)=&gt;</span>&#123;</span><br><span class="line">    <span class="comment">//当所有promise的都走成功状态时进入，res是所有promise的resolve的数据列表</span></span><br><span class="line">&#125;).<span class="title function_">catch</span>(<span class="function">(<span class="params">err</span>)=&gt;</span>&#123;</span><br><span class="line">    <span class="comment">// 只要有一个reject，那么就会来的catch</span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line">promise.<span class="title function_">rect</span>([p1,p2,p3]).<span class="title function_">then</span>(<span class="function">(<span class="params">res</span>)=&gt;</span>&#123;</span><br><span class="line">    <span class="comment">// 谁的结果最快，就是谁的then 和 catch</span></span><br><span class="line">&#125;)</span><br><span class="line">promise.<span class="title function_">any</span>([p1,p2,p3]).<span class="title function_">then</span>(<span class="function">(<span class="params">res</span>)=&gt;</span>&#123;</span><br><span class="line">    <span class="comment">// 谁的结果最快，并且是成功状态，就是谁的then，所有都是rejected时，就会走catch</span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">// ES11</span></span><br><span class="line">promise.<span class="title function_">allSettled</span>([p1,p2,p3]).<span class="title function_">then</span>(<span class="function">(<span class="params">res</span>)=&gt;</span>&#123;</span><br><span class="line">    <span class="comment">//不管状态时什么，只要有结果都会进入，返回对应的对象</span></span><br><span class="line">    <span class="comment">//[&#123;status:rejected,reason:&quot;异常值&quot;&#125;,&#123;status:fulfilled,value:&quot;返回值&quot;&#125;]</span></span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<h4 id="Iterator-迭代器"><a href="#Iterator-迭代器" class="headerlink" title="Iterator 迭代器"></a>Iterator 迭代器</h4><ul>
<li><p>很多语言都有<strong>迭代器</strong>，迭代器是让<strong>用户</strong>可以<strong>遍历访问</strong>数组、链表、哈希表。。。这些<strong>容器对象</strong> 的 对象</p>
<ul>
<li>这些容器对象就是<strong>可迭代对象</strong></li>
</ul>
</li>
<li><p>JS中：迭代器是一个具体对象，这个<strong>对象符合迭代器协议</strong>，JS的标准就是 <strong>next</strong></p>
<ul>
<li><strong>要求一：</strong>必须是<strong>参数个数小于等于1</strong>的函数</li>
<li><strong>要求二：</strong>必须返回存在 <code>done</code> 和 <code>value</code> 的对象<ul>
<li><strong>done(是否结束):</strong> 如果迭代器可以产生下一个值，<code>done</code> 为 <code>false</code>，如果是最后一个，<code>done</code>  为 <code>true</code></li>
<li><strong>value:</strong> <code>done</code>为<code>true</code>时可以省略</li>
</ul>
</li>
</ul>
</li>
<li><p><strong>可迭代对象</strong></p>
<ul>
<li>然有一个**[Symbol.iterator]**函数</li>
<li>执行 <strong>[Symbol.iterator]</strong> 得到一个<strong>迭代器函数</strong>，这个迭代器函数就有next() 方法</li>
<li>原生可迭代对象：<code>String、Array、Map、Set、argument、NodeList</code></li>
</ul>
</li>
<li><p><strong>应用场景</strong>  可迭代对象才能用的语法</p>
<ul>
<li><p>可以用<strong>for of</strong> 变量</p>
<ul>
<li>拿到变量那个可迭代对象的 [Symbol.iterator] 并执行 得到迭代器，执行next() 返回 value，直到 done 为 true 结束</li>
</ul>
</li>
<li><p>展开语法 (ES9 对象内部展开，是js做了特殊处理，不是迭代器做的)</p>
</li>
<li><p>结构赋值</p>
</li>
<li><p>yield*</p>
</li>
<li><p>构造函数参数：new Map( iterator )、new Set() 、new WeakSet()、new WeakMap() 参数都有是可迭代对象</p>
</li>
<li><p>Promise.all( iterator )、Array.from()</p>
</li>
</ul>
</li>
</ul>
<p>对象迭代器</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">      将infos变成一个可迭代对象</span></span><br><span class="line"><span class="comment">      1.必须实现一个特定的函数: [Symbol.iterator]</span></span><br><span class="line"><span class="comment">      2.这个函数需要返回一个迭代器(这个迭代器用于 迭代当前的对象)</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="keyword">const</span> infoss = &#123;</span><br><span class="line">    <span class="attr">friends</span>: [<span class="string">&quot;kobe&quot;</span>, <span class="string">&quot;james&quot;</span>, <span class="string">&quot;curry&quot;</span>],</span><br><span class="line">    <span class="attr">a</span>:<span class="number">1</span>,</span><br><span class="line">    <span class="attr">b</span>:<span class="number">2</span>,</span><br><span class="line">    [<span class="title class_">Symbol</span>.<span class="property">iterator</span>]: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">let</span> index = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">let</span> item = <span class="title class_">Object</span>.<span class="title function_">entries</span>(<span class="variable language_">this</span>);</span><br><span class="line">        <span class="keyword">const</span> infosIterator = &#123;</span><br><span class="line">            <span class="attr">next</span>: <span class="function">() =&gt;</span> &#123;</span><br><span class="line">                <span class="keyword">if</span> (index &lt; item.<span class="property">length</span>) &#123;</span><br><span class="line">                    <span class="keyword">return</span> &#123;</span><br><span class="line">                        <span class="attr">done</span>: <span class="literal">false</span>,</span><br><span class="line">                        <span class="attr">value</span>: item[index++],</span><br><span class="line">                    &#125;;</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    <span class="keyword">return</span> &#123; <span class="attr">done</span>: <span class="literal">true</span> &#125;;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;,</span><br><span class="line">        &#125;;</span><br><span class="line">        <span class="keyword">return</span> infosIterator;</span><br><span class="line">    &#125;,</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span>(<span class="keyword">const</span> item <span class="keyword">of</span> infoss)&#123;</span><br><span class="line">    <span class="keyword">if</span> (item[<span class="number">1</span>] == <span class="string">&quot;kobe&quot;</span>) &#123;</span><br><span class="line">        <span class="keyword">break</span>; <span class="comment">// 可以用 break 或 continue 终断</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(item)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> inter = infoss[<span class="title class_">Symbol</span>.<span class="property">iterator</span>]()</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(inter.<span class="title function_">next</span>())</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(inter.<span class="title function_">next</span>());</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(inter.<span class="title function_">next</span>());</span><br></pre></td></tr></table></figure>

<blockquote>
<p>  让对象变成可迭代对象</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="title class_">Object</span>.<span class="property"><span class="keyword">prototype</span></span>[<span class="title class_">Symbol</span>.<span class="property">iterator</span>] = <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">    <span class="comment">// const keys = Object.keys(this)</span></span><br><span class="line">    <span class="comment">// const values = Object.values(this)</span></span><br><span class="line">    <span class="keyword">const</span> entries = <span class="title class_">Object</span>.<span class="title function_">entries</span>(<span class="variable language_">this</span>);</span><br><span class="line">    <span class="keyword">let</span> index = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">const</span> iterator = &#123;</span><br><span class="line">        <span class="attr">next</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">            <span class="keyword">if</span> (index &lt; entries.<span class="property">length</span>) &#123;</span><br><span class="line">                <span class="keyword">return</span> &#123; <span class="attr">done</span>: <span class="literal">false</span>, <span class="attr">value</span>: entries[index++] &#125;;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                <span class="keyword">return</span> &#123; <span class="attr">done</span>: <span class="literal">true</span> &#125;;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;,</span><br><span class="line">    &#125;;</span><br><span class="line">    <span class="keyword">return</span> iterator;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>



<h4 id="Generator-生成器"><a href="#Generator-生成器" class="headerlink" title="Generator 生成器"></a>Generator 生成器</h4><h4 id="ES-Module"><a href="#ES-Module" class="headerlink" title="ES Module"></a>ES Module</h4><h3 id="ES7-ES13新特性"><a href="#ES7-ES13新特性" class="headerlink" title="ES7 ~ ES13新特性"></a>ES7 ~ ES13新特性</h3><h4 id="ES8-ES2017"><a href="#ES8-ES2017" class="headerlink" title="ES8(ES2017)"></a>ES8(ES2017)</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 对象方法</span></span><br><span class="line"><span class="title class_">Object</span>.<span class="title function_">keys</span>(obj); <span class="comment">// [key,key,key]</span></span><br><span class="line"><span class="title class_">Object</span>.<span class="title function_">values</span>(obj); <span class="comment">// [value,value,value]</span></span><br><span class="line"><span class="title class_">Object</span>.<span class="title function_">entries</span>(obj); <span class="comment">// [[key,value],[key,value],[key,value]]</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//对数组/字符串操作(了解)</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="title class_">Object</span>.<span class="title function_">entries</span>([<span class="string">&quot;abc&quot;</span>, <span class="string">&quot;cba&quot;</span>])); <span class="comment">// [[0,&#x27;abc&#x27;],[1,[cba]]</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="title class_">Object</span>.<span class="title function_">entries</span>(<span class="string">&quot;Hello&quot;</span>));</span><br><span class="line"></span><br><span class="line"><span class="comment">// 字符串填充</span></span><br><span class="line"><span class="keyword">const</span> minute = <span class="string">&quot;15&quot;</span>.<span class="title function_">padStart</span>(<span class="number">2</span>, <span class="string">&quot;0&quot;</span>) <span class="comment">// 不足两位，从前面用0 填充</span></span><br><span class="line"><span class="keyword">const</span> second = <span class="string">&quot;6&quot;</span>.<span class="title function_">padStart</span>(<span class="number">2</span>, <span class="string">&quot;0&quot;</span>) <span class="comment">// 不足两位，从前面用0 填充</span></span><br><span class="line"><span class="keyword">const</span> pend = <span class="string">&quot;6&quot;</span>.<span class="title function_">padEnd</span>(<span class="number">3</span>, <span class="string">&quot;0&quot;</span>) <span class="comment">//  // 不足三位，从后面用0 填充</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`<span class="subst">$&#123;minute&#125;</span>:<span class="subst">$&#123;second&#125;</span>`</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">// Trailing Commas 允许尾部逗号</span></span><br><span class="line"><span class="keyword">function</span>(<span class="params">a,b,</span>)&#123;&#125; </span><br><span class="line"></span><br><span class="line"><span class="comment">// 获取属性描述符</span></span><br><span class="line"><span class="title class_">Object</span>.<span class="title function_">getOwnPropertyDescriptors</span>()</span><br></pre></td></tr></table></figure>

<h5 id="async-await"><a href="#async-await" class="headerlink" title="async&#x2F;await"></a>async&#x2F;await</h5><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">``</span><span class="string">`</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">#### ES9(ES2018)</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">##### 异步迭代器 </span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">##### 对象展开运算</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">##### Promise finallly</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">#### ES10(ES2019)</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">`</span><span class="string">``</span>javascript</span><br><span class="line"><span class="comment">// flat 按照指定深度，数组扁平化</span></span><br><span class="line"><span class="keyword">const</span> nums = [<span class="number">10</span>, <span class="number">20</span>, [<span class="number">111</span>, <span class="number">222</span>], [<span class="number">333</span>, <span class="number">444</span>], [[<span class="number">123</span>, <span class="number">321</span>], [<span class="number">231</span>, <span class="number">312</span>]]]</span><br><span class="line"><span class="keyword">const</span> newNums1 = nums.<span class="title function_">flat</span>(<span class="number">1</span>) <span class="comment">// 扁平化一层</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// flatMap</span></span><br><span class="line"><span class="keyword">let</span> list = [</span><br><span class="line">    <span class="string">&#x27;hello word&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;aaa bbb&#x27;</span></span><br><span class="line">]</span><br><span class="line"><span class="keyword">const</span> finalMessages = list.<span class="title function_">flatMap</span>(<span class="function">(<span class="params">item</span>) =&gt;</span> item.<span class="title function_">split</span>(<span class="string">&quot; &quot;</span>));</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(finalMessages); <span class="comment">// [hello,word,aaa,bbb]</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// trimStart、trimEnd</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27; msg ms &#x27;</span>.<span class="title function_">trimStart</span>()) <span class="comment">// 去除前面的空格</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 将ES8的 对象方法 Object.entries(obj) 二维数组反转回对象</span></span><br><span class="line"><span class="title class_">Object</span>.<span class="title function_">fromEntries</span>(entries)</span><br></pre></td></tr></table></figure>

<h4 id="ES11-ES2020"><a href="#ES11-ES2020" class="headerlink" title="ES11(ES2020)"></a>ES11(ES2020)</h4><h5 id="BigInt"><a href="#BigInt" class="headerlink" title="BigInt||?.||??"></a>BigInt||?.||??</h5><blockquote>
<p>  表示超过number范围的大整数</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// BigInt </span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="title class_">Number</span>.<span class="property">MAX_SAFE_INTEGER</span>); <span class="comment">// number能表示的最大安全整数 9007199254740991</span></span><br><span class="line"><span class="keyword">const</span> num1 = <span class="number">9007199254740992n</span>;</span><br><span class="line"><span class="keyword">const</span> num2 = <span class="number">9007199254740993n</span>;</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(num1, num2);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 其他</span></span><br><span class="line"><span class="comment">// 空值合并运算符，如果data 为 null或undefined时 将 默认值赋值给info</span></span><br><span class="line"><span class="keyword">let</span> info = data ?? <span class="string">&#x27;默认值&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 可选链</span></span><br><span class="line"><span class="keyword">let</span> obj = &#123;</span><br><span class="line">    <span class="attr">info</span>:&#123;</span><br><span class="line">        <span class="attr">innerInfo</span>:<span class="keyword">function</span>(<span class="params"></span>)&#123;</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;&#x27;</span>)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 如果 obj存在info,info存在innerInfo时，才调用</span></span><br><span class="line">obj?.<span class="property">inof</span>?.<span class="property">innerInfo</span>?.()</span><br><span class="line"></span><br><span class="line"><span class="comment">// for in 遍历对象标准化</span></span><br></pre></td></tr></table></figure>

<h5 id="Promise-allSettled"><a href="#Promise-allSettled" class="headerlink" title="Promise.allSettled"></a>Promise.allSettled</h5><h4 id="ES12-ES2021"><a href="#ES12-ES2021" class="headerlink" title="ES12(ES2021)"></a>ES12(ES2021)</h4><h5 id="FinalizationRegistry"><a href="#FinalizationRegistry" class="headerlink" title="FinalizationRegistry"></a>FinalizationRegistry</h5><blockquote>
<p>  将某个对象注册进去，被GC回收时产生回调</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> obj = &#123; <span class="attr">name</span>: <span class="string">&quot;why&quot;</span>, <span class="attr">age</span>: <span class="number">18</span> &#125;;</span><br><span class="line"><span class="keyword">let</span> info = &#123; <span class="attr">name</span>: <span class="string">&quot;kobe&quot;</span>, <span class="attr">age</span>: <span class="number">30</span> &#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> finalRegistry = <span class="keyword">new</span> <span class="title class_">FinalizationRegistry</span>(<span class="function">(<span class="params">value</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;某一个对象被回收了:&quot;</span>, value);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">finalRegistry.<span class="title function_">register</span>(obj, <span class="string">&quot;why&quot;</span>);</span><br><span class="line">finalRegistry.<span class="title function_">register</span>(info, <span class="string">&quot;kobe&quot;</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// obj = null</span></span><br><span class="line">info = <span class="literal">null</span>;</span><br></pre></td></tr></table></figure>

<h5 id="WeakRefs"><a href="#WeakRefs" class="headerlink" title="WeakRefs"></a>WeakRefs</h5><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> info = &#123; <span class="attr">name</span>: <span class="string">&quot;why&quot;</span>, <span class="attr">age</span>: <span class="number">18</span> &#125;;</span><br><span class="line"><span class="keyword">let</span> obj = <span class="keyword">new</span> <span class="title class_">WeakRef</span>(info); <span class="comment">// 弱引用的方式指向 info 指向的地址 ，只要info=null</span></span><br><span class="line"><span class="keyword">let</span> obj2 = <span class="keyword">new</span> <span class="title class_">WeakRef</span>(info);</span><br></pre></td></tr></table></figure>

<h5 id="逻辑赋值运算符"><a href="#逻辑赋值运算符" class="headerlink" title="逻辑赋值运算符"></a>逻辑赋值运算符</h5><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 逻辑赋值运算符</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">foo</span>(<span class="params">message</span>) &#123;</span><br><span class="line">    <span class="comment">// 1.||逻辑赋值运算符</span></span><br><span class="line">    <span class="comment">// message = message || &quot;默认值&quot;</span></span><br><span class="line">    <span class="comment">// message ||= &quot;默认值&quot;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 2.??逻辑赋值运算符</span></span><br><span class="line">    <span class="comment">// message = message ?? &quot;默认值&quot;</span></span><br><span class="line">    message ??= <span class="string">&quot;默认值&quot;</span>;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(message);</span><br><span class="line">    </span><br><span class="line">    obj &amp;&amp;= obj.<span class="property">name</span>  <span class="comment">// 如果obj对象的name存在，就把obj的name赋值个obj</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="大数字分隔符"><a href="#大数字分隔符" class="headerlink" title="大数字分隔符"></a>大数字分隔符</h5><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 用下划线分割很大的而书中</span></span><br><span class="line"><span class="keyword">let</span> a = <span class="number">100000000</span></span><br><span class="line"><span class="keyword">let</span> b = <span class="number">100_000_000</span></span><br></pre></td></tr></table></figure>

<h5 id="replaceAll"><a href="#replaceAll" class="headerlink" title="replaceAll"></a>replaceAll</h5><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> msg = <span class="string">&#x27;aaa_aaa_bbb_ccc&#x27;</span>;</span><br><span class="line">msg.<span class="title function_">replace</span>(<span class="string">&quot;aaa&quot;</span>,<span class="string">&quot;ddd&quot;</span>) <span class="comment">// 只替换第一个aaa</span></span><br><span class="line">msg.<span class="title function_">replaceAll</span>(<span class="string">&quot;aaa&quot;</span>,<span class="string">&quot;ddd&quot;</span>) <span class="comment">// 全部aaa都替换</span></span><br></pre></td></tr></table></figure>

<h4 id="ES13-ES2022"><a href="#ES13-ES2022" class="headerlink" title="ES13(ES2022)"></a>ES13(ES2022)</h4><h5 id="at方法"><a href="#at方法" class="headerlink" title="at方法"></a>at方法</h5><blockquote>
<p>  通过at方法从数组或字符串中取值</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> list = [<span class="string">&#x27;aaa&#x27;</span>,<span class="string">&#x27;bbb&#x27;</span>,<span class="string">&#x27;ccc&#x27;</span>]</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(list.<span class="title function_">at</span>(<span class="number">1</span>)) <span class="comment">// 获取数组索引为1的元素 bbb</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(list.<span class="title function_">at</span>(-<span class="number">1</span>)) <span class="comment">// 数组最后一位，ccc</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> str = <span class="string">&#x27;hello&#x27;</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(str.<span class="title function_">at</span>(<span class="number">1</span>))</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(str.<span class="title function_">at</span>(-<span class="number">1</span>))</span><br></pre></td></tr></table></figure>

<h5 id="Object-hasOwn"><a href="#Object-hasOwn" class="headerlink" title="Object.hasOwn"></a>Object.hasOwn</h5><blockquote>
<p>  判断对象上是否有自己的指定属性</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 防止重写，用户自己的obj对象中也有 hasOwnProperty 这个方法</span></span><br><span class="line">obj.<span class="title function_">hasOwnProperty</span>(obj)  <span class="comment">// 判断obj对象上是否有name属性，不包含原型链的name，写在prototype原型上</span></span><br><span class="line"><span class="title class_">Object</span>.<span class="title function_">hasOwn</span>(obj,name)  <span class="comment">//  替代 obj.hasOwnProperty</span></span><br></pre></td></tr></table></figure>

<h5 id="Class-添加新成员"><a href="#Class-添加新成员" class="headerlink" title="Class 添加新成员"></a>Class 添加新成员</h5><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Person</span> &#123;</span><br><span class="line">    <span class="comment">// 1.实例属性</span></span><br><span class="line">    <span class="comment">// 对象属性: public 公共 -&gt; public instance fields</span></span><br><span class="line">    <span class="comment">// 所有实例都可以使用</span></span><br><span class="line">    height = <span class="number">1.88</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 对象属性: private 私有: 程序员之间的约定，还是能通过 p._intro 访问的</span></span><br><span class="line">    _intro = <span class="string">&quot;name is why&quot;</span>; <span class="comment">// p._intro 访问</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// ES13对象属性: private 私有，外面无法访问</span></span><br><span class="line">    #intro = <span class="string">&quot;name is why&quot;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 2.类属性(static)</span></span><br><span class="line">    <span class="comment">// 类属性: public</span></span><br><span class="line">    <span class="keyword">static</span> totalCount = <span class="string">&quot;70亿&quot;</span>; <span class="comment">// 通过 Person.totalCount 访问属性</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 类属性: private</span></span><br><span class="line">    <span class="keyword">static</span> #maleTotalCount = <span class="string">&quot;20亿&quot;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params">name, age</span>) &#123;</span><br><span class="line">        <span class="comment">// 对象中的属性: 在constructor通过this设置</span></span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">name</span> = name;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">age</span> = age;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">address</span> = <span class="string">&quot;广州市&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 3.静态代码块，第一次加载类的时候自动执行，用于初始化一些东西</span></span><br><span class="line">    <span class="keyword">static</span> &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;Hello World&quot;</span>);</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;Hello Person&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> p = <span class="keyword">new</span> <span class="title class_">Person</span>(<span class="string">&quot;why&quot;</span>, <span class="number">18</span>);</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(p);</span><br></pre></td></tr></table></figure>



<h3 id="其他"><a href="#其他" class="headerlink" title="其他"></a>其他</h3><h4 id="拷贝"><a href="#拷贝" class="headerlink" title="拷贝"></a>拷贝</h4><h5 id="浅拷贝"><a href="#浅拷贝" class="headerlink" title="浅拷贝"></a>浅拷贝</h5><blockquote>
<p>  只能拷贝一层，遇到引用类型的数据拷贝的也是引用地址</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> obj2 = &#123; ...obj &#125;</span><br><span class="line"><span class="keyword">const</span> obj2 = <span class="title class_">Object</span>.<span class="title function_">assign</span>(&#123;&#125;,obj)</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> obj2 = &#123;&#125;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">const</span> key <span class="keyword">in</span> obj) &#123;</span><br><span class="line">    obj2[key] = obj[key];</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="深拷贝"><a href="#深拷贝" class="headerlink" title="深拷贝"></a>深拷贝</h5><blockquote>
<p>  遇到引用类型的数据拷贝的，不是引用地址，而是会创建新的对象，对<strong>性能很不友好</strong></p>
</blockquote>
<p>JSON方式</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> *  JSON.parse(JSON.stringify(info));</span></span><br><span class="line"><span class="comment"> *      1、函数引用无法添加到新对象 </span></span><br><span class="line"><span class="comment"> *      2、无法拷贝值为 undefined 的属性</span></span><br><span class="line"><span class="comment"> *      3、无法拷贝 [Symbol()] </span></span><br><span class="line"><span class="comment"> *      4、如果有对自己循环引用的对象，会报错</span></span><br><span class="line"><span class="comment"> */</span></span><br></pre></td></tr></table></figure>

<p>自定义</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">deepCopy</span>(<span class="params">originValue</span>) &#123;</span><br><span class="line">    <span class="comment">// 1.如果是原始类型, 直接返回</span></span><br><span class="line"></span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 3、其他特殊类型 </span></span><br><span class="line">    <span class="comment">//      Object.prototype.toString.call(originValue) == &#x27;[object Set]&#x27; // 做自己的操作 </span></span><br><span class="line">    <span class="comment">//      Object.prototype.toString.call(originValue) == &#x27;[object Function]&#x27; // 直接返回</span></span><br><span class="line">    <span class="comment">//      </span></span><br><span class="line">    <span class="comment">// 2、如果不是原始类型和特殊类型，判断是对象就创建&#123;&#125;，数组就创建[]</span></span><br><span class="line">    <span class="comment">// 3.通过遍历实现拷贝</span></span><br><span class="line">    <span class="comment">// 4.其实就是在浅拷贝的基础上加一层判断，不是直接赋值，而是赋 deepCopy 过的值</span></span><br><span class="line">    <span class="comment">// 5.返回新对象</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 深拷贝</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">isObject</span>(<span class="params">value</span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> valueType = <span class="keyword">typeof</span> value</span><br><span class="line">  <span class="keyword">return</span> (value !== <span class="literal">null</span>) &amp;&amp; ( valueType === <span class="string">&quot;object&quot;</span> || valueType === <span class="string">&quot;function&quot;</span> )</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 深拷贝核心 </span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">deepCopy</span>(<span class="params">originValue</span>) &#123;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 1.如果是原始类型, 直接返回</span></span><br><span class="line">    <span class="keyword">if</span> (!<span class="title function_">isObject</span>(originValue)) &#123;</span><br><span class="line">        <span class="keyword">return</span> originValue;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 2.如果是函数function类型, 不需要进行深拷贝，其实可以直接从 isObject 取代</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">typeof</span> originValue === <span class="string">&quot;function&quot;</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> originValue;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 3.如果是对象类型, 才需要创建对象</span></span><br><span class="line">    <span class="keyword">const</span> newObj = <span class="title class_">Array</span>.<span class="title function_">isArray</span>(originValue) ? [] : &#123;&#125;;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">const</span> key <span class="keyword">in</span> originValue) &#123; <span class="comment">// 数组的k是索引，可以和对象一样 for in 判断</span></span><br><span class="line">        newObj[key] = <span class="title function_">deepCopy</span>(originValue[key]);</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> newObj;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 深拷贝详细</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">deepCopy</span>(<span class="params">originValue,map = <span class="keyword">new</span> <span class="built_in">WeakMap</span>()</span>) &#123;</span><br><span class="line">    <span class="comment">// 0.如果值是Symbol的类型</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">typeof</span> originValue === <span class="string">&quot;symbol&quot;</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="title class_">Symbol</span>(originValue.<span class="property">description</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 1.如果是原始类型, 直接返回</span></span><br><span class="line">    <span class="keyword">if</span> (!<span class="title function_">isObject</span>(originValue)) &#123;</span><br><span class="line">        <span class="keyword">return</span> originValue;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 2.如果是set类型</span></span><br><span class="line">    <span class="keyword">if</span> (originValue <span class="keyword">instanceof</span> <span class="title class_">Set</span>) &#123;</span><br><span class="line">        <span class="keyword">const</span> newSet = <span class="keyword">new</span> <span class="title class_">Set</span>();</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">const</span> setItem <span class="keyword">of</span> originValue) &#123;</span><br><span class="line">            newSet.<span class="title function_">add</span>(<span class="title function_">deepCopy</span>(setItem));</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> newSet;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 3.如果是函数function类型, 不需要进行深拷贝，其实可以直接从 isObject 取代</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">typeof</span> originValue === <span class="string">&quot;function&quot;</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> originValue;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 4-1.如果是对象类型, 才需要创建对象</span></span><br><span class="line">   <span class="keyword">if</span> (map.<span class="title function_">get</span>(originValue)) &#123; <span class="comment">// map为了解决循环引用问题</span></span><br><span class="line">       <span class="keyword">return</span> map.<span class="title function_">get</span>(originValue);</span><br><span class="line">   &#125;</span><br><span class="line">    <span class="keyword">const</span> newObj = <span class="title class_">Array</span>.<span class="title function_">isArray</span>(originValue) ? [] : &#123;&#125;;</span><br><span class="line">    map.<span class="title function_">set</span>(originValue, newObj);</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">const</span> key <span class="keyword">in</span> originValue) &#123; <span class="comment">// 数组的k是索引，可以和对象一样 for in 判断</span></span><br><span class="line">        newObj[key] = <span class="title function_">deepCopy</span>(originValue[key],map);</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 4-1 单独遍历symbol，for in 变量不到 symbol</span></span><br><span class="line">    <span class="keyword">const</span> symbolKeys = <span class="title class_">Object</span>.<span class="title function_">getOwnPropertySymbols</span>(originValue);</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">const</span> symbolKey <span class="keyword">of</span> symbolKeys) &#123;</span><br><span class="line">        newObj[<span class="title class_">Symbol</span>(symbolKey.<span class="property">description</span>)] = <span class="title function_">deepCopy</span>(</span><br><span class="line">            originValue[symbolKey],</span><br><span class="line">            map</span><br><span class="line">        );</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> newObj;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="事件总线"><a href="#事件总线" class="headerlink" title="事件总线"></a>事件总线</h4><blockquote>
<p>  用于跨组件的数据传递</p>
</blockquote>
<h5 id="Vue2-的-EventBus"><a href="#Vue2-的-EventBus" class="headerlink" title="Vue2 的 EventBus"></a>Vue2 的 EventBus</h5><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="title class_">Vue</span> <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">EventBus</span> = <span class="keyword">new</span> <span class="title class_">Vue</span>() <span class="comment">// 全局使用</span></span><br><span class="line"></span><br><span class="line"><span class="title class_">Vue</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">$EventBus</span> = <span class="keyword">new</span> <span class="title class_">Vue</span>() <span class="comment">// 不需要导入导出</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 组件中发送事件</span></span><br><span class="line"><span class="variable language_">this</span>.<span class="property">$EventBus</span>.$emit(<span class="string">&quot;event&quot;</span>,<span class="string">&#x27;hello&#x27;</span>) </span><br><span class="line"><span class="comment">// 组件中监听数据的触发</span></span><br><span class="line"><span class="variable language_">this</span>.<span class="property">$EventBus</span>.$on(<span class="string">&quot;event&quot;</span>,<span class="function">(<span class="params">data</span>)=&gt;</span>&#123;&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">// Vue3 删除推荐使用 miss 第三方库</span></span><br></pre></td></tr></table></figure>

<h5 id="手写事件总线"><a href="#手写事件总线" class="headerlink" title="手写事件总线"></a>手写事件总线</h5><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">EventBus</span> &#123;</span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">events</span> = &#123;&#125;;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">emit</span>(<span class="params">event, data</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="property">events</span>[event].<span class="property">length</span> &gt; <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="variable language_">this</span>.<span class="property">events</span>[event].<span class="title function_">forEach</span>(<span class="function">(<span class="params">fn</span>) =&gt;</span> &#123;</span><br><span class="line">                <span class="title function_">fn</span>(data);</span><br><span class="line">            &#125;);  </span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">on</span>(<span class="params">event, callback</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (!<span class="variable language_">this</span>.<span class="property">events</span>[event]) &#123;</span><br><span class="line">            <span class="variable language_">this</span>.<span class="property">events</span>[event] = [];</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">events</span>[event].<span class="title function_">push</span>(callback);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">off</span>(<span class="params">event, callback</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="property">events</span>[event]) &#123;</span><br><span class="line">            <span class="variable language_">this</span>.<span class="property">events</span>[event].<span class="title function_">forEach</span>(<span class="function">(<span class="params">fn, index</span>) =&gt;</span> &#123;</span><br><span class="line">                <span class="keyword">if</span> (fn == callback) &#123;</span><br><span class="line">                    <span class="variable language_">this</span>.<span class="property">events</span>[event].<span class="title function_">splice</span>(index, <span class="number">1</span>);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">clear</span>(<span class="params">event</span>) &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">events</span>[event] = <span class="literal">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> <span class="title class_">Evb</span> = <span class="keyword">new</span> <span class="title class_">EventBus</span>();</span><br><span class="line"></span><br><span class="line"><span class="comment">// 监听</span></span><br><span class="line"><span class="title class_">Evb</span>.<span class="title function_">on</span>(<span class="string">&quot;eventClick&quot;</span>, <span class="function">(<span class="params">data</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(data);</span><br><span class="line">&#125;);</span><br><span class="line"><span class="title class_">Evb</span>.<span class="title function_">on</span>(<span class="string">&quot;eventClick&quot;</span>, <span class="function">(<span class="params">data</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;第二次&quot;</span>, data);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="title class_">Evb</span>.<span class="title function_">on</span>(<span class="string">&quot;lick&quot;</span>, <span class="function">(<span class="params">data</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(data);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 触发</span></span><br><span class="line"><span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="title class_">Evb</span>.<span class="title function_">emit</span>(<span class="string">&quot;eventClick&quot;</span>, <span class="string">&quot;触发了 eventClick 的 emit&quot;</span>);</span><br><span class="line">&#125;, <span class="number">5000</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="title class_">Evb</span>.<span class="title function_">emit</span>(<span class="string">&quot;lick&quot;</span>, <span class="string">&quot;触发了 lick 的 emit&quot;</span>);</span><br><span class="line">&#125;, <span class="number">6000</span>);</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="网络请求"><a href="#网络请求" class="headerlink" title="网络请求"></a>网络请求</h4><h5 id="HTTP"><a href="#HTTP" class="headerlink" title="HTTP"></a>HTTP</h5><h5 id="XHR"><a href="#XHR" class="headerlink" title="XHR"></a>XHR</h5><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 1. 创建XMLHttpRequest对象</span></span><br><span class="line"><span class="keyword">const</span> xhr = <span class="keyword">new</span> <span class="title class_">XMLHttpRequest</span>()</span><br><span class="line"></span><br><span class="line"><span class="comment">// 2. 监听状态改变</span></span><br><span class="line">xhr.<span class="property">onreadystatechange</span> = <span class="keyword">function</span>(<span class="params"></span>)&#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(xhr.<span class="property">readyStat</span>)</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(xhr.<span class="property">response</span>) <span class="comment">// 拿到结果 字符串</span></span><br><span class="line">    <span class="keyword">const</span> resJSON = <span class="title class_">JSON</span>.<span class="title function_">parse</span>(xhr.<span class="property">response</span>) <span class="comment">// 解析结果成对象，responseType 默认是text</span></span><br><span class="line">    </span><br><span class="line">    <span class="comment">//xhr.responseText/xhr.responseXML</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 其他事件监听</span></span><br><span class="line">xhr.<span class="property">onloadstart</span> = <span class="keyword">function</span>(<span class="params"></span>)&#123;&#125; <span class="comment">// 开始请求</span></span><br><span class="line">xhr.<span class="property">onprogress</span> = <span class="keyword">function</span>(<span class="params"></span>)&#123;&#125;  <span class="comment">// 一个响应数据表到达，一般用于展示文件上传进度</span></span><br><span class="line">xhr.<span class="property">onabort</span> = <span class="keyword">function</span>(<span class="params"></span>)&#123;&#125; <span class="comment">// 取消请求</span></span><br><span class="line">xhr.<span class="property">ontimeout</span></span><br><span class="line">xhr.<span class="property">onerror</span></span><br><span class="line">xhr.<span class="property">onload</span> = <span class="keyword">function</span>(<span class="params"></span>)&#123;&#125; <span class="comment">// 请求成功，xhr.onreadystatechange 并且 xhr.readyStat == 4</span></span><br><span class="line">xhr.<span class="property">loadend</span>  <span class="comment">// load、error、timeout、abort之后触发</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 告知xhr等会获取到的数据的类型</span></span><br><span class="line"><span class="comment">// 如已知拿到的是JSON数据，后端也会通过Response Headers 的 Content-Type 告知前端该怎么处理他返回的数据</span></span><br><span class="line"><span class="comment">// get</span></span><br><span class="line">xhr.<span class="property">responseType</span> = <span class="string">&#x27;json&#x27;</span> <span class="comment">// 后不需要JSON解析 </span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 3. 配置请求 open</span></span><br><span class="line"><span class="comment">// method 请求方式</span></span><br><span class="line">xhr.<span class="title function_">open</span>(<span class="string">&quot;get&quot;</span>,<span class="string">&quot;http://xxxx/xxx?a=1&amp;b=2&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 4-1. get请求 发送, 通过query传递数据</span></span><br><span class="line">xhr.<span class="title function_">send</span>()</span><br><span class="line"></span><br><span class="line"><span class="comment">// 4-2 post请求 发送</span></span><br><span class="line"><span class="comment">// 告诉服务器，用什么样的方式解析我前端给你的数据 </span></span><br><span class="line">xhr.<span class="title function_">setRequestHeader</span>(<span class="string">&quot;Content-Type&quot;</span>,<span class="string">&quot;application/x-www-form-urlencoded&quot;</span>)</span><br><span class="line">xhr.<span class="title function_">send</span>(<span class="string">&quot;a=1&amp;b=2&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 4-3 post请求 发送FormData数据</span></span><br><span class="line"><span class="keyword">const</span> formData = <span class="keyword">new</span> <span class="title class_">FormData</span>(formElement) <span class="comment">// 将表单元素转FormData</span></span><br><span class="line">xhr.<span class="title function_">send</span>(formData)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 4-4 post请求 json 数据</span></span><br><span class="line">xhr.<span class="title function_">setRequestHeader</span>(<span class="string">&quot;Content-Type&quot;</span>,<span class="string">&quot;application/json&quot;</span>)</span><br><span class="line">xhr.<span class="title function_">send</span>(<span class="title class_">JSON</span>.<span class="title function_">stringify</span>(&#123;<span class="attr">a</span>:<span class="number">1</span>,<span class="attr">b</span>:<span class="number">2</span>&#125;))</span><br><span class="line"></span><br><span class="line"><span class="comment">// 1.超市时间的设置，浏览器达到过期时间还没有获取结果时，自动取消本次请求</span></span><br><span class="line">xhr.<span class="property">timeout</span> = <span class="number">3000</span></span><br><span class="line">xhr.<span class="property">ontimeout</span> = <span class="keyword">function</span>(<span class="params"></span>) &#123; <span class="comment">// 当超时的时候</span></span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;请求过期: timeout&quot;</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 手动取消请求，某个事件中</span></span><br><span class="line">xhr.<span class="title function_">abort</span>() <span class="comment">// 取消请求</span></span><br><span class="line">xhr.<span class="property">onabort</span> = <span class="keyword">function</span>(<span class="params"></span>)&#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;请求被取消&#x27;</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h5 id="Fetch"><a href="#Fetch" class="headerlink" title="Fetch"></a>Fetch</h5><p>XHR的优化方案</p>
<ul>
<li>类似封装好的XHR，直接返回值是一个promise（发送成功调用resolve，失败调用reject）</li>
<li>不同XML，所有操作到在一个对象上</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 基本使用</span></span><br><span class="line"><span class="title function_">fetch</span>(<span class="string">&quot;http://123.207.32.32:8000/home/multidata&quot;</span>)</span><br><span class="line">    .<span class="title function_">then</span>(<span class="function">(<span class="params">res</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">// 1.获取到response，是一个流</span></span><br><span class="line">    <span class="keyword">const</span> response = res;</span><br><span class="line">    <span class="comment">// 2.获取具体的结果，如果是json数据，就用json()</span></span><br><span class="line">    <span class="keyword">return</span> response.<span class="title function_">json</span>();</span><br><span class="line">&#125;)</span><br><span class="line">    .<span class="title function_">then</span>(<span class="function">(<span class="params">res</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;res:&quot;</span>, res);</span><br><span class="line">&#125;)</span><br><span class="line">    .<span class="title function_">catch</span>(<span class="function">(<span class="params">err</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;err:&quot;</span>, err);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 优化</span></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">getData</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> response = <span class="keyword">await</span> <span class="title function_">fetch</span>(<span class="string">&quot;http://123.207.32.32:8000/home/multidata&quot;</span>);</span><br><span class="line">    <span class="keyword">const</span> res = <span class="keyword">await</span> response.<span class="title function_">json</span>();</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;res:&quot;</span>, res);</span><br><span class="line">&#125;</span><br><span class="line"><span class="title function_">getData</span>();</span><br><span class="line"></span><br><span class="line"><span class="comment">// 参数</span></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">getData</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="comment">// const response = await fetch(</span></span><br><span class="line">    <span class="comment">// 	&quot;http://123.207.32.32:1888/02_param/postjson&quot;,</span></span><br><span class="line">    <span class="comment">// 	&#123;</span></span><br><span class="line">    <span class="comment">// 		method: &quot;post&quot;,</span></span><br><span class="line">    <span class="comment">// 		// headers: &#123;</span></span><br><span class="line">    <span class="comment">// 		//   &quot;Content-type&quot;: &quot;application/json&quot;</span></span><br><span class="line">    <span class="comment">// 		// &#125;,</span></span><br><span class="line">    <span class="comment">// 		body: JSON.stringify(&#123;</span></span><br><span class="line">    <span class="comment">// 			name: &quot;why&quot;,</span></span><br><span class="line">    <span class="comment">// 			age: 18,</span></span><br><span class="line">    <span class="comment">// 		&#125;),</span></span><br><span class="line">    <span class="comment">// 	&#125;</span></span><br><span class="line">    <span class="comment">// );</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">const</span> formData = <span class="keyword">new</span> <span class="title class_">FormData</span>();</span><br><span class="line">    formData.<span class="title function_">append</span>(<span class="string">&quot;name&quot;</span>, <span class="string">&quot;why&quot;</span>);</span><br><span class="line">    formData.<span class="title function_">append</span>(<span class="string">&quot;age&quot;</span>, <span class="number">18</span>);</span><br><span class="line">    <span class="keyword">const</span> response = <span class="keyword">await</span> <span class="title function_">fetch</span>(</span><br><span class="line">        <span class="string">&quot;http://123.207.32.32:1888/02_param/postform&quot;</span>,</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="attr">method</span>: <span class="string">&quot;post&quot;</span>,</span><br><span class="line">            <span class="attr">body</span>: formData,</span><br><span class="line">        &#125;</span><br><span class="line">    );</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 获取response状态，ok == 200-299</span></span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(response.<span class="property">ok</span>, response.<span class="property">status</span>, response.<span class="property">statusText</span>);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">const</span> res = <span class="keyword">await</span> response.<span class="title function_">json</span>();</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;res:&quot;</span>, res);</span><br><span class="line">&#125;</span><br><span class="line"><span class="title function_">getData</span>();</span><br></pre></td></tr></table></figure>



</article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta">文章作者: </span><span class="post-copyright-info"><a href="http://example.com">lzoxun</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta">文章链接: </span><span class="post-copyright-info"><a href="http://example.com/2023/07/22/web/web-script-js/">http://example.com/2023/07/22/web/web-script-js/</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta">版权声明: </span><span class="post-copyright-info">本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来自 <a href="http://example.com" target="_blank">学习笔记</a>！</span></div></div><div class="tag_share"><div class="post-meta__tag-list"></div><div class="post_share"><div class="social-share" data-image="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png" data-sites="facebook,twitter,wechat,weibo,qq"></div><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/butterfly-extsrc/sharejs/dist/css/share.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/sharejs/dist/js/social-share.min.js" defer></script></div></div><nav class="pagination-post" id="pagination"><div class="prev-post pull-left"><a href="/2023/07/22/web/web-script-ts/" title="TypeScript 基础"><div class="cover" style="background: var(--default-bg-color)"></div><div class="pagination-info"><div class="label">上一篇</div><div class="prev_info">TypeScript 基础</div></div></a></div><div class="next-post pull-right"><a href="/2023/07/22/web/web-admin/" title="后台管理系统"><div class="cover" style="background: var(--default-bg-color)"></div><div class="pagination-info"><div class="label">下一篇</div><div class="next_info">后台管理系统</div></div></a></div></nav></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="is-center"><div class="avatar-img"><img src= "" data-lazy-src="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/></div><div class="author-info__name">lzoxun</div><div class="author-info__description"></div></div><div class="card-info-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">108</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">1</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">0</div></a></div><a id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/liaozhongxun"><i class="fab fa-github"></i><span>Follow Me</span></a><div class="card-info-social-icons is-center"><a class="social-icon" href="https://github.com/liaozhongxun" target="_blank" title="Github"><i class="fab fa-github" style="color: #24292e;"></i></a><a class="social-icon" href="mailto:869664233@gmail.com" target="_blank" title="Email"><i class="fas fa-envelope" style="color: #4a7dbe;"></i></a></div></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn fa-shake"></i><span>公告</span></div><div class="announcement_content">这是我的文档</div></div><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="fas fa-stream"></i><span>目录</span><span class="toc-percentage"></span></div><div class="toc-content"><ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#JS-%E5%9F%BA%E7%A1%80%EF%BC%88ECMSscript%EF%BC%89"><span class="toc-number">1.</span> <span class="toc-text">JS 基础（ECMSscript）</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%A6%82%E5%BF%B5"><span class="toc-number">1.1.</span> <span class="toc-text">概念</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E8%AE%A4%E8%AF%86-JavaScript"><span class="toc-number">1.1.1.</span> <span class="toc-text">认识 JavaScript</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80%E7%9A%84%E5%8E%86%E5%8F%B2"><span class="toc-number">1.1.2.</span> <span class="toc-text">编程语言的历史</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#JavaScript-%E7%9A%84%E5%8E%86%E5%8F%B2"><span class="toc-number">1.1.3.</span> <span class="toc-text">JavaScript 的历史</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#JavaScript-%E4%B8%8E-ECMAScript-%E6%A0%87%E5%87%86%E7%9A%84%E5%85%B3%E7%B3%BB"><span class="toc-number">1.1.4.</span> <span class="toc-text">JavaScript 与 ECMAScript 标准的关系</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#JavaScript-%E7%9A%84%E7%89%B9%E7%82%B9"><span class="toc-number">1.1.5.</span> <span class="toc-text">JavaScript 的特点</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#JavaScript-%E7%BC%96%E5%86%99%E4%BD%8D%E7%BD%AE"><span class="toc-number">1.1.6.</span> <span class="toc-text">JavaScript 编写位置</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%B3%A8%E9%87%8A"><span class="toc-number">1.1.7.</span> <span class="toc-text">注释</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%9C%89%E6%B5%8F%E8%A7%88%E5%99%A8%E4%BA%A4%E4%BA%92"><span class="toc-number">1.1.8.</span> <span class="toc-text">有浏览器交互</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%A6%82%E4%BD%95%E5%AE%9A%E4%B9%89%E5%8F%98%E9%87%8F"><span class="toc-number">1.1.9.</span> <span class="toc-text">如何定义变量</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B"><span class="toc-number">1.1.10.</span> <span class="toc-text">数据类型</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%A3%80%E6%B5%8B%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B"><span class="toc-number">1.1.11.</span> <span class="toc-text">检测数据类型</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2"><span class="toc-number">1.1.12.</span> <span class="toc-text">数据类型转换</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E8%BF%90%E7%AE%97%E7%AC%A6"><span class="toc-number">1.1.13.</span> <span class="toc-text">运算符</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%89%A7%E8%A1%8C%E8%AF%AD%E5%8F%A5"><span class="toc-number">1.2.</span> <span class="toc-text">执行语句</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%88%86%E6%94%AF"><span class="toc-number">1.2.1.</span> <span class="toc-text">分支</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%BE%AA%E7%8E%AF"><span class="toc-number">1.2.2.</span> <span class="toc-text">循环</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%95%B0%E7%BB%84"><span class="toc-number">1.3.</span> <span class="toc-text">数组</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%AD%97%E7%AC%A6%E4%B8%B2"><span class="toc-number">1.4.</span> <span class="toc-text">字符串</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%87%8D%E8%A6%81%E6%A6%82%E5%BF%B5"><span class="toc-number">1.5.</span> <span class="toc-text">重要概念</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#JS-API"><span class="toc-number">2.</span> <span class="toc-text">JS API</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#DOM"><span class="toc-number">2.1.</span> <span class="toc-text">DOM</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#BOM"><span class="toc-number">2.2.</span> <span class="toc-text">BOM</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#JS-%E9%AB%98%E7%BA%A7"><span class="toc-number">3.</span> <span class="toc-text">JS 高级</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#JavaScript-%E7%9A%84-this"><span class="toc-number">3.1.</span> <span class="toc-text">JavaScript 的 this</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%B5%8F%E8%A7%88%E5%99%A8%E7%9A%84%E8%BF%90%E8%A1%8C%E5%8E%9F%E7%90%86"><span class="toc-number">3.2.</span> <span class="toc-text">浏览器的运行原理</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E9%80%9A%E8%BF%87URL%E6%8B%BF%E5%88%B0%E8%B5%84%E6%BA%90"><span class="toc-number">3.2.1.</span> <span class="toc-text">通过URL拿到资源</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%B5%8F%E8%A7%88%E5%86%85%E6%A0%B8"><span class="toc-number">3.2.2.</span> <span class="toc-text">浏览内核</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E9%A1%B5%E9%9D%A2%E6%B8%B2%E6%9F%93%E8%AF%A6%E7%BB%86%E6%B5%81%E7%A8%8B"><span class="toc-number">3.2.3.</span> <span class="toc-text">页面渲染详细流程</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E7%89%B9%E6%AE%8A%E8%A7%A3%E6%9E%90-composite-%E5%90%88%E6%88%90"><span class="toc-number">3.2.4.</span> <span class="toc-text">特殊解析 composite 合成</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Script-%E5%85%83%E7%B4%A0%E7%9A%84%E4%BC%98%E5%8C%96"><span class="toc-number">3.2.5.</span> <span class="toc-text">Script 元素的优化</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#defer-%E5%B1%9E%E6%80%A7"><span class="toc-number">3.2.5.1.</span> <span class="toc-text">defer 属性</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#async-%E5%B1%9E%E6%80%A7"><span class="toc-number">3.2.5.2.</span> <span class="toc-text">async 属性</span></a></li></ol></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#JS-%E5%BC%95%E6%93%8E"><span class="toc-number">3.3.</span> <span class="toc-text">JS 引擎</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#V8%E5%BC%95%E6%93%8E%E6%89%A7%E8%A1%8C%E5%8E%9F%E7%90%86"><span class="toc-number">3.3.1.</span> <span class="toc-text">V8引擎执行原理</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#V8%E6%A0%B8%E5%BF%83%E6%A6%82%E5%BF%B5"><span class="toc-number">3.3.2.</span> <span class="toc-text">V8核心概念</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#Parse-%E8%A7%A3%E6%9E%90%E6%A8%A1%E5%9D%97"><span class="toc-number">3.3.2.1.</span> <span class="toc-text">Parse 解析模块</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#lgnition-%E8%A7%A3%E9%87%8A%E5%99%A8"><span class="toc-number">3.3.2.2.</span> <span class="toc-text">lgnition 解释器</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#TurboFan-%E7%BC%96%E8%AF%91%E5%99%A8"><span class="toc-number">3.3.2.3.</span> <span class="toc-text">TurboFan 编译器</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E6%A8%A1%E5%9D%97"><span class="toc-number">3.3.2.4.</span> <span class="toc-text">垃圾回收模块</span></a></li></ol></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%B5%8F%E8%A7%88%E5%99%A8%E4%B8%AD-JS-%E7%9A%84%E8%BF%90%E8%A1%8C%E5%8E%9F%E7%90%86"><span class="toc-number">3.4.</span> <span class="toc-text">浏览器中 JS 的运行原理</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%88%9D%E5%A7%8B%E5%8C%96%E5%85%A8%E5%B1%80%E5%AF%B9%E8%B1%A1"><span class="toc-number">3.4.1.</span> <span class="toc-text">初始化全局对象</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%89%A7%E8%A1%8C%E4%B8%8A%E4%B8%8B%E6%96%87%E6%A0%88%EF%BC%88ECS%EF%BC%89"><span class="toc-number">3.4.2.</span> <span class="toc-text">执行上下文栈（ECS）</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E6%89%A7%E8%A1%8C%E4%B8%8A%E4%B8%8B%E6%96%87"><span class="toc-number">3.4.2.1.</span> <span class="toc-text">执行上下文</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E6%89%A7%E8%A1%8C%E4%B8%8A%E4%B8%8B%E6%96%87%E7%9A%84-VO-%E8%AF%A6%E8%A7%A3"><span class="toc-number">3.4.2.2.</span> <span class="toc-text">执行上下文的 VO 详解</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E6%89%A7%E8%A1%8C%E4%B8%8A%E4%B8%8B%E6%96%87%E7%9A%84%E4%BD%9C%E7%94%A8%E5%9F%9F%E9%93%BE"><span class="toc-number">3.4.2.3.</span> <span class="toc-text">执行上下文的作用域链</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E9%97%AD%E5%8C%85"><span class="toc-number">3.4.2.4.</span> <span class="toc-text">闭包</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E6%89%A7%E8%A1%8C%E4%B8%8A%E4%B8%8B%E6%96%87%E7%9A%84-This"><span class="toc-number">3.4.2.5.</span> <span class="toc-text">执行上下文的 This</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86%E4%B8%8E%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6"><span class="toc-number">3.4.3.</span> <span class="toc-text">内存管理与垃圾回收</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#js%E7%9A%84%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6"><span class="toc-number">3.4.3.1.</span> <span class="toc-text">js的垃圾回收</span></a></li></ol></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%89%8B%E5%86%99-call-apply-bind"><span class="toc-number">3.5.</span> <span class="toc-text">手写 call-apply-bind</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#JavaScript-%E5%87%BD%E6%95%B0%E5%A2%9E%E5%BC%BA"><span class="toc-number">3.6.</span> <span class="toc-text">JavaScript 函数增强</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%87%BD%E6%95%B0%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%B1%9E%E6%80%A7"><span class="toc-number">3.6.1.</span> <span class="toc-text">函数对象的属性</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E7%BA%AF%E5%87%BD%E6%95%B0"><span class="toc-number">3.6.2.</span> <span class="toc-text">纯函数</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%9F%AF%E9%87%8C%E5%8C%96-%EF%BC%88Currying%EF%BC%89"><span class="toc-number">3.6.3.</span> <span class="toc-text">柯里化 （Currying）</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E9%A2%9D%E5%A4%96%E7%9F%A5%E8%AF%86%EF%BC%88%E5%B0%91%E7%94%A8%EF%BC%89"><span class="toc-number">3.6.4.</span> <span class="toc-text">额外知识（少用）</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#with"><span class="toc-number">3.6.4.1.</span> <span class="toc-text">with</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#eval"><span class="toc-number">3.6.4.2.</span> <span class="toc-text">eval</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E4%B8%A5%E6%A0%BC%E6%A8%A1%E5%BC%8F"><span class="toc-number">3.6.4.3.</span> <span class="toc-text">严格模式</span></a></li></ol></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#JavaScript-%E5%AF%B9%E8%B1%A1%E5%A2%9E%E5%BC%BA"><span class="toc-number">3.7.</span> <span class="toc-text">JavaScript 对象增强</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%95%B0%E6%8D%AE%E5%B1%9E%E6%80%A7%E6%8F%8F%E8%BF%B0%E7%AC%A6"><span class="toc-number">3.7.1.</span> <span class="toc-text">数据属性描述符</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%AD%98%E5%8F%96%E5%B1%9E%E6%80%A7%E6%8F%8F%E8%BF%B0%E7%AC%A6"><span class="toc-number">3.7.2.</span> <span class="toc-text">存取属性描述符</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%AF%B9%E8%B1%A1%E4%B8%AD%E7%9A%84%E5%86%99%E6%B3%95"><span class="toc-number">3.7.3.</span> <span class="toc-text">对象中的写法</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1"><span class="toc-number">3.8.</span> <span class="toc-text">面向对象</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%8E%9F%E5%9E%8B"><span class="toc-number">3.8.1.</span> <span class="toc-text">原型</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%8E%9F%E5%9E%8B%E9%93%BE"><span class="toc-number">3.8.2.</span> <span class="toc-text">原型链</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#new-%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86"><span class="toc-number">3.8.3.</span> <span class="toc-text">new 实现原理</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%AF%B9%E8%B1%A1%E6%96%B9%E6%B3%95%E8%A1%A5%E5%85%85"><span class="toc-number">3.8.4.</span> <span class="toc-text">对象方法补充</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E4%B8%89%E5%A4%A7%E7%89%B9%E6%80%A7"><span class="toc-number">3.8.5.</span> <span class="toc-text">面向对象三大特性</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E5%B0%81%E8%A3%85"><span class="toc-number">3.8.5.1.</span> <span class="toc-text">封装</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E7%BB%A7%E6%89%BF"><span class="toc-number">3.8.5.2.</span> <span class="toc-text">继承</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E5%A4%9A%E6%80%81"><span class="toc-number">3.8.5.3.</span> <span class="toc-text">多态</span></a></li></ol></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#ES6-%E7%9A%84-Class"><span class="toc-number">3.9.</span> <span class="toc-text">ES6 的 Class</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%AF%B9%E6%AF%94%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0"><span class="toc-number">3.9.1.</span> <span class="toc-text">对比构造函数</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E7%B1%BB%E7%9A%84%E6%8F%8F%E8%BF%B0%E7%AC%A6"><span class="toc-number">3.9.2.</span> <span class="toc-text">类的描述符</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#ES6-%E7%9A%84%E7%BB%A7%E6%89%BF"><span class="toc-number">3.9.3.</span> <span class="toc-text">ES6 的继承</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#ES6-%E5%A2%9E%E5%BC%BA"><span class="toc-number">3.10.</span> <span class="toc-text">ES6 增强</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%AF%B9%E8%B1%A1%E5%AD%97%E9%9D%A2%E9%87%8F"><span class="toc-number">3.10.1.</span> <span class="toc-text">对象字面量</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E8%A7%A3%E6%9E%84"><span class="toc-number">3.10.2.</span> <span class="toc-text">解构</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%96%B0%E7%9A%84ECMA%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%8F%8F%E8%BF%B0"><span class="toc-number">3.10.3.</span> <span class="toc-text">新的ECMA代码执行描述</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#let-const"><span class="toc-number">3.10.4.</span> <span class="toc-text">let&#x2F;const</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%AF%B9%E8%B1%A1"><span class="toc-number">3.11.</span> <span class="toc-text">对象</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#ES6%E5%87%BD%E6%95%B0%E5%A2%9E%E5%BC%BA"><span class="toc-number">3.11.1.</span> <span class="toc-text">ES6函数增强</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%B1%95%E5%BC%80"><span class="toc-number">3.11.2.</span> <span class="toc-text">展开</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%95%B0%E5%80%BC%E8%A1%A8%E7%A4%BA"><span class="toc-number">3.11.3.</span> <span class="toc-text">数值表示</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Symbol"><span class="toc-number">3.11.4.</span> <span class="toc-text">Symbol</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Set-and-Map-%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84"><span class="toc-number">3.11.5.</span> <span class="toc-text">Set and Map 数据结构</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#Set"><span class="toc-number">3.11.5.1.</span> <span class="toc-text">Set</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#Map"><span class="toc-number">3.11.5.2.</span> <span class="toc-text">Map</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#WeakSet"><span class="toc-number">3.11.5.3.</span> <span class="toc-text">WeakSet</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#WeakMap"><span class="toc-number">3.11.5.4.</span> <span class="toc-text">WeakMap</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Proxy-SReflect"><span class="toc-number">3.11.6.</span> <span class="toc-text">Proxy&#x2F;SReflect</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E5%9B%9E%E9%A1%BEvue2%E5%93%8D%E5%BA%94%E5%BC%8F%E5%8E%9F%E7%90%86"><span class="toc-number">3.11.6.1.</span> <span class="toc-text">回顾vue2响应式原理</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#Proxy"><span class="toc-number">3.11.6.2.</span> <span class="toc-text">Proxy</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#Reflect%EF%BC%88%E5%8F%8D%E5%B0%84%EF%BC%89"><span class="toc-number">3.11.6.3.</span> <span class="toc-text">Reflect（反射）</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Promise"><span class="toc-number">3.11.7.</span> <span class="toc-text">Promise</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E7%B1%BB%E6%96%B9%E6%B3%95"><span class="toc-number">3.11.7.1.</span> <span class="toc-text">类方法</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Iterator-%E8%BF%AD%E4%BB%A3%E5%99%A8"><span class="toc-number">3.11.8.</span> <span class="toc-text">Iterator 迭代器</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Generator-%E7%94%9F%E6%88%90%E5%99%A8"><span class="toc-number">3.11.9.</span> <span class="toc-text">Generator 生成器</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#ES-Module"><span class="toc-number">3.11.10.</span> <span class="toc-text">ES Module</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#ES7-ES13%E6%96%B0%E7%89%B9%E6%80%A7"><span class="toc-number">3.12.</span> <span class="toc-text">ES7 ~ ES13新特性</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#ES8-ES2017"><span class="toc-number">3.12.1.</span> <span class="toc-text">ES8(ES2017)</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#async-await"><span class="toc-number">3.12.1.1.</span> <span class="toc-text">async&#x2F;await</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#ES11-ES2020"><span class="toc-number">3.12.2.</span> <span class="toc-text">ES11(ES2020)</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#BigInt"><span class="toc-number">3.12.2.1.</span> <span class="toc-text">BigInt||?.||??</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#Promise-allSettled"><span class="toc-number">3.12.2.2.</span> <span class="toc-text">Promise.allSettled</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#ES12-ES2021"><span class="toc-number">3.12.3.</span> <span class="toc-text">ES12(ES2021)</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#FinalizationRegistry"><span class="toc-number">3.12.3.1.</span> <span class="toc-text">FinalizationRegistry</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#WeakRefs"><span class="toc-number">3.12.3.2.</span> <span class="toc-text">WeakRefs</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E9%80%BB%E8%BE%91%E8%B5%8B%E5%80%BC%E8%BF%90%E7%AE%97%E7%AC%A6"><span class="toc-number">3.12.3.3.</span> <span class="toc-text">逻辑赋值运算符</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E5%A4%A7%E6%95%B0%E5%AD%97%E5%88%86%E9%9A%94%E7%AC%A6"><span class="toc-number">3.12.3.4.</span> <span class="toc-text">大数字分隔符</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#replaceAll"><span class="toc-number">3.12.3.5.</span> <span class="toc-text">replaceAll</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#ES13-ES2022"><span class="toc-number">3.12.4.</span> <span class="toc-text">ES13(ES2022)</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#at%E6%96%B9%E6%B3%95"><span class="toc-number">3.12.4.1.</span> <span class="toc-text">at方法</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#Object-hasOwn"><span class="toc-number">3.12.4.2.</span> <span class="toc-text">Object.hasOwn</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#Class-%E6%B7%BB%E5%8A%A0%E6%96%B0%E6%88%90%E5%91%98"><span class="toc-number">3.12.4.3.</span> <span class="toc-text">Class 添加新成员</span></a></li></ol></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%85%B6%E4%BB%96"><span class="toc-number">3.13.</span> <span class="toc-text">其他</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%8B%B7%E8%B4%9D"><span class="toc-number">3.13.1.</span> <span class="toc-text">拷贝</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E6%B5%85%E6%8B%B7%E8%B4%9D"><span class="toc-number">3.13.1.1.</span> <span class="toc-text">浅拷贝</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E6%B7%B1%E6%8B%B7%E8%B4%9D"><span class="toc-number">3.13.1.2.</span> <span class="toc-text">深拷贝</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BA%8B%E4%BB%B6%E6%80%BB%E7%BA%BF"><span class="toc-number">3.13.2.</span> <span class="toc-text">事件总线</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#Vue2-%E7%9A%84-EventBus"><span class="toc-number">3.13.2.1.</span> <span class="toc-text">Vue2 的 EventBus</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E6%89%8B%E5%86%99%E4%BA%8B%E4%BB%B6%E6%80%BB%E7%BA%BF"><span class="toc-number">3.13.2.2.</span> <span class="toc-text">手写事件总线</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E7%BD%91%E7%BB%9C%E8%AF%B7%E6%B1%82"><span class="toc-number">3.13.3.</span> <span class="toc-text">网络请求</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#HTTP"><span class="toc-number">3.13.3.1.</span> <span class="toc-text">HTTP</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#XHR"><span class="toc-number">3.13.3.2.</span> <span class="toc-text">XHR</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#Fetch"><span class="toc-number">3.13.3.3.</span> <span class="toc-text">Fetch</span></a></li></ol></li></ol></li></ol></li></ol></div></div><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2023/07/22/window/win-11/" title="win 11 set">win 11 set</a><time datetime="2023-07-22T07:14:09.700Z" title="发表于 2023-07-22 15:14:09">2023-07-22</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2023/07/22/window/win-gitbash/" title="git bash">git bash</a><time datetime="2023-07-22T07:14:09.700Z" title="发表于 2023-07-22 15:14:09">2023-07-22</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2023/07/22/window/win-wsl/" title="wsl">wsl</a><time datetime="2023-07-22T07:14:09.700Z" title="发表于 2023-07-22 15:14:09">2023-07-22</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2023/07/22/window/win-main/" title="window">window</a><time datetime="2023-07-22T07:14:09.700Z" title="发表于 2023-07-22 15:14:09">2023-07-22</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2023/07/22/web/%E5%85%BC%E5%AE%B9%E9%97%AE%E9%A2%98/" title="兼容问题">兼容问题</a><time datetime="2023-07-22T07:14:09.699Z" title="发表于 2023-07-22 15:14:09">2023-07-22</time></div></div></div></div></div></div></main><footer id="footer"><div id="footer-wrap"><div class="copyright">&copy;2020 - 2023 By lzoxun</div><div class="framework-info"><span>框架 </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo</a><span class="footer-separator">|</span><span>主题 </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="translateLink" type="button" title="简繁转换">繁</button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside_config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><button id="go-up" type="button" title="回到顶部"><span class="scroll-percent"></span><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><script src="/js/tw_cn.js"></script><script src="https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox/fancybox.umd.min.js"></script><script src="https://cdn.jsdelivr.net/npm/instant.page/instantpage.min.js" type="module"></script><script src="https://cdn.jsdelivr.net/npm/vanilla-lazyload/dist/lazyload.iife.min.js"></script><script src="https://cdn.jsdelivr.net/npm/node-snackbar/dist/snackbar.min.js"></script><script>function panguFn () {
  if (typeof pangu === 'object') pangu.autoSpacingPage()
  else {
    getScript('https://cdn.jsdelivr.net/npm/pangu/dist/browser/pangu.min.js')
      .then(() => {
        pangu.autoSpacingPage()
      })
  }
}

function panguInit () {
  if (false){
    GLOBAL_CONFIG_SITE.isPost && panguFn()
  } else {
    panguFn()
  }
}

document.addEventListener('DOMContentLoaded', panguInit)</script><div class="js-pjax"></div><script id="canvas_nest" defer="defer" color="0,0,255" opacity="0.7" zIndex="-1" count="99" mobile="false" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/dist/canvas-nest.min.js"></script><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script><div id="local-search"><div class="search-dialog"><nav class="search-nav"><span class="search-dialog-title">搜索</span><span id="loading-status"></span><button class="search-close-button"><i class="fas fa-times"></i></button></nav><div class="is-center" id="loading-database"><i class="fas fa-spinner fa-pulse"></i><span>  数据库加载中</span></div><div class="search-wrap"><div id="local-search-input"><div class="local-search-box"><input class="local-search-box--input" placeholder="搜索文章" type="text"/></div></div><hr/><div class="no-result" id="local-search-results"></div><div id="local-search-stats-wrap"></div></div></div><div id="search-mask"></div><script src="/js/search/local-search.js"></script></div></div><script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"pluginRootPath":"live2dw/","pluginJsPath":"lib/","pluginModelPath":"assets/","tagMode":false,"log":false,"model":{"jsonPath":"/live2dw/assets/haruto.model.json"},"display":{"position":"right","width":100,"height":200,"right":300},"mobile":{"show":true}});</script></body></html>